在haskell中处理具有灵活大小的列表元组

时间:2013-10-14 05:44:25

标签: haskell

我正在学习Haskell,这个问题可能非常愚蠢,但对不起我不知道答案

我有一个带有4元组列表的函数,这些列表的大小可能不同,但在元组中它们具有相同的大小

foo ([a],[b],[c],[d]) = concat [[a],[b])

它不适用于大小一号的列表 例如

foo ([1],[2],[3],[4]) // works fine 
foo ([1,2] , [2,3] , [3,4] , [5,7]) or any larger size of those list generate error

任何暗示要概括它?

2 个答案:

答案 0 :(得分:1)

就像源代码文本[1]表示具有单个元素(值1)的列表一样,源代码文本[a]表示具有单个元素的列表,即变量a 1 。它表示任何大小的列表,a表示列表的单个元素,而不是列表。

在等式的左侧,[a]将是仅匹配包含恰好一个元素(不是零,而不是2或3或更多)的列表的模式;该单个元素的值可以通过等式右边的a来引用。

所以这段代码:

foo ([a],[b],[c],[d]) = concat [[a],[b]]

给出了将foo应用于4个单例列表元组的结果的定义。它需要前两个列表中的单个元素(ab),将它们包装在新的单例列表中([a][b]),将这两个列表放入另一个列表,用于列出列表([[a],[b]]),然后将该列表传递给函数(concat [[a],[b]])。

如果任何一个列表中有多个元素,或者为空,那么这个等式并没有说明foo的结果是什么。如果没有其他方程式帮助定义函数foo,那么如果在这种不符合要求的输入上调用foo,则会出现模式匹配错误。

如果(我怀疑)你想要的是说这个定义适用于任何 4列表的元组,那么你会这样写:

foo (a,b,c,d) = concat [a,b]

请注意abcd周围缺少方括号。此版本采用前两个列表(ab)的完整,将这些列表放在另一个列表中以制作列表列表([a,b]),然后将该列表传递给函数(concat [a,b])。

函数的类型(无论是从您的代码中推断出来还是由您声明)表示foo作为参数接收的元组中的内容是列表 2 ;你不必在列表的每个变量周围加上方括号 - 事实上你不能,因为这意味着其他非常具体的东西!如果要匹配任何可能的列表,只需编写a;写[a]表示列表必须是一个元素的列表,并且它只是由变量a自由匹配的元素,而不是列表本身。

每次使用方括号语法时,您都会编写一个包含固定数量元素的列表, 3 ,括号中的内容是列表中的各个元素。


1 [a]是值表达式的上下文中。如果在类型表达式中出现这种情况,则[a]是列表的类型,其元素为类型 a

2 从技术上讲,如果您在此处使用推断类型,那么在我建议的版本中根本不会限制cd的类型,因为它们未被使用,所以他们不必是名单。

3 除非您正在编写列表推导(例如[x + 1 | x <- [1, 2, 3]])或数字范围表达式(例如[1..n])。

答案 1 :(得分:0)

这应该有效:

foo (a:_,b:_,c:_,d:_)= concat [[a],[b]]

在上面的函数中,您只需模式匹配每个列表的参数的第一个元素。

一个更简单的代码:

foo (a:_,b:_,_,_)= [a, b]

在ghci:

ghci> foo ([1],[2],[3],[4])
[1,2]
ghci> foo ([1,2] , [2,3] , [3,4] , [5,7])
[1,2]