递归

2016-08-22 89 views
0

我想每两个元素挑错误类型形成一个列表,使一个新的列表,然后我得到这样的错误:递归

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)] 

任何人都可以帮助我吗?

+2

如果'[x1]'的类型是'[a]',那么'[x1]'的类型是什么? – leftaroundabout

回答

2

它通常在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不应该做正确的事情。

+0

这真的有道理。非常感谢! – kkkjjj

1

[],[x1],[x1, x2][[x1, x2], (test xs)]都必须具有相同类型才是可能的相同功能的值。我想你在第三希望在第二种情况下[[x1]][[x1, x2]],因为在那些两起案件是完全最多两个长度的一个大块。需要注意的是,你甚至都不需要,因为它是由第四涵盖的xs = []第三种情况。你也可以跳过导入Data.List.Split并利用其chunksOf 2实现此功能。