递归类型错误
Type error with recursion
我想从一个列表中每两个元素中选择一个来创建一个新列表,然后我得到这样的错误:
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)]
谁能帮帮我?
[]
、[x1]
、[x1, x2]
和 [[x1, x2], (test xs)]
都必须具有相同的类型才能成为同一函数的可能值。我想你在第二种情况下想要 [[x1]]
,在第三种情况下想要 [[x1, x2]]
,因为在这两种情况下,只有一个长度块最多为两个。请注意,您甚至不需要第三种情况,因为它已被第四种情况覆盖 xs
= []
。您也可以通过导入 Data.List.Split
并使用它的 chunksOf 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
正确地从输入列表中弹出了前两个元素。现在你需要重新组装它们。 [x1,x2]
正好在结果列表的第一个元素处,但是然后呢? chunksÀ2 xs
的类型为 [[a]]
,因此如果将其放入另一个 []
中,则类型为 [[[a]]]
。这显然包装太多了!
相反,您只想将 [x1,x2]
添加到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 [] = [[]]
但这不是正确的做法。
我想从一个列表中每两个元素中选择一个来创建一个新列表,然后我得到这样的错误:
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)]
谁能帮帮我?
[]
、[x1]
、[x1, x2]
和 [[x1, x2], (test xs)]
都必须具有相同的类型才能成为同一函数的可能值。我想你在第二种情况下想要 [[x1]]
,在第三种情况下想要 [[x1, x2]]
,因为在这两种情况下,只有一个长度块最多为两个。请注意,您甚至不需要第三种情况,因为它已被第四种情况覆盖 xs
= []
。您也可以通过导入 Data.List.Split
并使用它的 chunksOf 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
正确地从输入列表中弹出了前两个元素。现在你需要重新组装它们。 [x1,x2]
正好在结果列表的第一个元素处,但是然后呢? chunksÀ2 xs
的类型为 [[a]]
,因此如果将其放入另一个 []
中,则类型为 [[[a]]]
。这显然包装太多了!
相反,您只想将 [x1,x2]
添加到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 [] = [[]]
但这不是正确的做法。