递归
我想每两个元素挑错误类型形成一个列表,使一个新的列表,然后我得到这样的错误:递归
test.hs:4:20: error:
? Couldn't match expected type ‘[a]’ with actual type ‘a’
‘a’ is a rigid type variable bound by
the type signature for:
test :: forall a. [a] -> [[a]]
at test.hs:1:7
? In the expression: x1
In the expression: [x1]
In a case alternative: [x1] -> [x1]
? Relevant bindings include
x1 :: a (bound at test.hs:4:6)
list :: [a] (bound at test.hs:2:6)
test :: [a] -> [[a]] (bound at test.hs:2:1)
这里是我的代码:
test::[a]->[[a]]
test list = case list of
[] ->[]
[x1] ->[x1]
[x1,x2] ->[x1,x2]
x1:x2:xs ->[[x1,x2],(test xs)]
任何人都可以帮助我吗?
它通常在Haskell最好只写一个函数的不同条款 - 这样做同样的事情case
,但往往是更好的可读性。另外,请不要给你的函数名称如test
!
更好的是这样的:
chunksÀ2 :: [a] -> [[a]]
chunksÀ2 [] = []
chunksÀ2 [x1] = [x1]
chunksÀ2 [x1,x2] = [x1,x2]
chunksÀ2 (x1:x2:xs) = [[x1,x2], chunksÀ2 xs]
现在,这些条款必须独立进行类型检查。我将从第二个开始:
chunksÀ2 [x1] = [x1]
嗯。签名表示结果应该是一个嵌套列表,并且输入一个简单的列表。因此可以肯定,你居然是说:
chunksÀ2 [x1] = [[x1]]
这是一个列表,它的唯一元素是一个元素的列表。
下一个子句类似:
chunksÀ2 [x1,x2] = [[x1,x2]]
注意
chunksÀ2 [x1,x2] = [[x1],[x2]]
也将是可能的。 (练习:为什么是你不想要的东西)
它有趣的是递归的子句。您已正确弹出输入列表中前两个元素,其模式匹配为x1:x2:xs
。现在你需要重新组装它们。在结果列表的第一个元素是正确的,但呢? chunksÀ2 xs
有[[a]]
,所以如果你把它放在另一个[]
你会有类型[[[a]]]
。这显然是太多的包装!
取而代之,您只需要预先到chunksÀ2 xs
。那么,使用cons运算符,你也用于模式匹配:
chunksÀ2 (x1:x2:xs) = [x1,x2] : chunksÀ2 xs
最后是空的子句。这实际上是你写作的方式,但你知道为什么吗?需要注意的是[]
可以有任何列表的你喜欢的类型:
Prelude> [] :: [Int]
[]
Prelude> [] :: [String]
[]
Prelude> [] :: [[(Double,[Maybe Bool])]]
[]
在
chunksÀ2 [] = []
你确实有
chunksÀ2 ([] :: [a]) = [] :: [[a]]
你可能也写
chunksÀ2 [] = [[]]
但那个w不应该做正确的事情。
这真的有道理。非常感谢! – kkkjjj
[]
,[x1]
,[x1, x2]
和[[x1, x2], (test xs)]
都必须具有相同类型才是可能的相同功能的值。我想你在第三希望在第二种情况下[[x1]]
和[[x1, x2]]
,因为在那些两起案件是完全最多两个长度的一个大块。需要注意的是,你甚至都不需要,因为它是由第四涵盖的xs
= []
第三种情况。你也可以跳过导入Data.List.Split
并利用其chunksOf 2
实现此功能。
如果'[x1]'的类型是'[a]',那么'[x1]'的类型是什么? – leftaroundabout