Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 递归类型错误_List_Haskell_Recursion_Types_Type Mismatch - Fatal编程技术网

List 递归类型错误

List 递归类型错误,list,haskell,recursion,types,type-mismatch,List,Haskell,Recursion,Types,Type Mismatch,我想从一个列表中选取每两个元素来创建一个新列表,然后我会得到如下错误: 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

我想从一个列表中选取每两个元素来创建一个新列表,然后我会得到如下错误:

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)
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]
这是我的代码:

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
=
[]
。您还可以通过导入
数据.List.Split
并使用其
块2

[]
[x1]
[x1,x2]
[[x1,x2],(test xs)]
来跳过实现此功能。所有这些都必须具有相同类型才能成为同一函数的可能值。我认为您希望在第二种情况下使用
[[x1]]
,在第三种情况下使用
[[x1,x2]]]
,因为在这两种情况下,正好有一个块的长度最多为两个。请注意,您甚至不需要第三种情况,因为第四种情况涵盖了
xs
=
[]
。您还可以通过导入
Data.List.Split
并使用其
chunksOf 2
跳过实现此函数。在Haskell中,通常更倾向于只编写函数的不同子句–这与
case
做的事情相同,但通常可读性更好。另外,请不要给函数命名,如
test

最好是这样:

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)
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À2xs
的类型为
[[a]]
,因此如果您将其放在另一个
[[/code>中,您将得到类型为
[[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 ([] :: [a]) = [] :: [[a]]
你也可以写

chunksÀ2 [] = [[]]

但是这样做是不对的。

在Haskell中,通常更倾向于只编写函数的不同子句–这与
case
做的事情相同,但通常可读性更好。另外,请不要给函数命名,如
test

最好是这样:

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)
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À2xs
的类型为
[[a]]
,因此如果您将其放在另一个
[[/code>中,您将得到类型为
[[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 ([] :: [a]) = [] :: [[a]]
你也可以写

chunksÀ2 [] = [[]]

如果
[x1]
的类型是
[a]
,那么
[x1]
的类型是什么?如果
[x1]
的类型是
[a]
,那么
[x1]
的类型是什么?这才是真正有意义的。谢谢!这确实有道理。谢谢!