Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.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
Haskell 发生检查:无法构造无限类型:t~[t]_Haskell - Fatal编程技术网

Haskell 发生检查:无法构造无限类型:t~[t]

Haskell 发生检查:无法构造无限类型:t~[t],haskell,Haskell,我开始学习哈斯克尔。我正在试着运行这个代码 -- Helpers.hs module Helpers where lst1 +++ lst2 = if null lst1 then lst2 else (head lst1) : (tail lst1 +++ lst2) reverse2 lst = if null lst then [] else reverse2 (tail lst) : (he

我开始学习哈斯克尔。我正在试着运行这个代码

-- Helpers.hs
module Helpers
where

lst1 +++ lst2 = if null lst1
            then lst2
            else (head lst1) : (tail lst1 +++ lst2)


reverse2 lst = if null lst
           then []
           else reverse2 (tail lst) : (head lst)
我发现这个错误:

D:\Haskell\project>cabal configure
Resolving dependencies...
Configuring one-0.1.0.0...

D:\Haskell\project>cabal build
Building one-0.1.0.0...
Preprocessing executable 'one' for one-0.1.0.0...
[1 of 2] Compiling Helpers          ( src\Utils\Helpers.hs, dist\build\one\one-t
mp\Helpers.o )

src\Utils\Helpers.hs:11:21:
    Occurs check: cannot construct the infinite type: t ~ [t]
    Relevant bindings include
      lst :: [[t]] (bound at src\Utils\Helpers.hs:9:10)
      reverse2 :: [[t]] -> [t] (bound at src\Utils\Helpers.hs:9:1)
    In the first argument of `(:)', namely `reverse2 (tail lst)'
    In the expression: reverse2 (tail lst) : (head lst)
如何修复它?

反向2(尾部lst)类型为
[a]
,而
头部lst
类型为
a
。同时,
运算符的类型为
a->[a]->[a]
。当您尝试执行
reverse2(tail-lst):(head-lst)
时,Haskell认为
head-lst
是一个列表,其元素的类型与
reverse2(tail-lst)
相同,即
head-lst:[[a]]
。然而,
head lst
也必须与
reverse2(tail lst)
的元素类型相同,这意味着
reverse2(tail lst):[[a]]]
,但是
head lst
必须是
[[[a]]]]
,然后
reverse2(tail lst)
必须是
[a]]]]]
,,我想你能看到这是怎么回事


发生此问题的原因是您使用的
不正确。如果要将元素附加到列表中,最简单的方法是
reverse2(tail lst)+[head lst]

正如jwodder所写内容的扩展说明一样,如果显式键入内容,则可以得到更有用的错误消息:

Prelude> let reverse2 :: [a] -> [a]; reverse2 lst = if null lst then [] else (reverse2 (tail lst)) : (head lst)

<interactive>:6:70:
    Couldn't match expected type ‘a’ with actual type ‘[a]’
      ‘a’ is a rigid type variable bound by
          the type signature for reverse2 :: [a] -> [a] at <interactive>:6:17
    Relevant bindings include
      lst :: [a] (bound at <interactive>:6:38)
      reverse2 :: [a] -> [a] (bound at <interactive>:6:29)
    In the first argument of ‘(:)’, namely ‘(reverse2 (tail lst))’
    In the expression: (reverse2 (tail lst)) : (head lst)
Prelude>let reverse2::[a]->[a];reverse2 lst=如果lst为空,则[]否则(reverse2(尾部lst)):(头部lst)
:6:70:
无法将预期类型“a”与实际类型“[a]”匹配
“a”是一个刚性类型变量,由
reverse2::[a]->[a]at:6:17的类型签名
相关绑定包括
lst::[a](于6:38绑定)
背面2::[a]->[a](于6:29绑定)
在“(:)”的第一个参数中,即“(reverse2(tail lst))”
在表达式中:(反转2(尾部lst)):(头部lst)

因此,当前的问题是,您将错误类型的参数传递给了
运算符,haskell试图使它们成为正确的类型,而它努力使它们成为正确的类型会导致错误消息变得模糊

作为一般策略,当像这样出现奇怪的错误消息时,我开始将类型签名应用于它抱怨的内容,这样haskell就不会试图推断出与我的意图相去甚远的类型签名

使用您的代码执行此操作时,我首先将其添加到
reverse2

reverse2 :: [t] -> [t]
reverse2 lst = if null lst
           then []
           else reverse2 (tail lst) : (head lst)
这会将错误消息更改为:

Couldn't match expected type ‘t’ with actual type ‘[t]’
      ‘t’ is a rigid type variable bound by
          the type signature for reverse2 :: [t] -> [t]
          at /tmp/flycheck-stackov.hs:6:13
    Relevant bindings include
      lst :: [t] (bound at /tmp/flycheck-stackov.hs:7:10)
      reverse2 :: [t] -> [t] (bound at /tmp/flycheck-stackov.hs:7:1)
    In the first argument of ‘(:)’, namely ‘reverse2 (tail lst)’
    In the expression: reverse2 (tail lst) : (head lst)
好的,现在它说“当查看
的第一个参数时,我期望类型
t
,但得到类型
[t]

事实上,如果我们问ghci的类型是什么,我们会看到:

Prelude> :t (:)
(:) :: a -> [a] -> [a]
因此,
的左参数必须是单个项,右参数必须是列表。您正在使用左侧的列表,右侧的单个项目

要按照您想要的方式连接,正如另一个答案所说,您应该使用
++

reverse2 :: [t] -> [t]
reverse2 lst = if null lst
           then []
           else reverse2 (tail lst) ++ [head lst]

(另外,您的
main
例程中有一个类型错误。您想说
putStrLn$reverse2[2,8,7]
而不是
putStrLn.reverse2[2,8,7]

您应该能够通过以下方式修复它:

reverse2 lst = if null lst
   then []
   else reverse2 (tail lst) ++ [head lst]
@jwodder已经解释了这不起作用的更多理论原因

注意,上面的实现效率很低,因为
++
完全遍历它的第一个参数,然后进行连接

下面是一个更复杂的方法

reverse3 lst = 
    let aux lst acc = if null lst then acc else aux (tail lst) (head lst : acc) 
    in aux lst []

显式注释类型通常很有帮助(例如,您编写的
reverse2::[a]->[a]

,因为您什么时候能够使用类型的列表
[[a][[a][[a][[a][a][a][a][a][a][a][a][a][a]了?这就是类型
a][a]你也在描述,它是非常单元格和错误倾向的,在样式上使用NULL。模式匹配是非常优越的。我认为这确实是正确的答案,但是我会考虑添加解释“JWODDER给出的”这样的答案可以更完整。我也建议添加模式匹配策略作为一种替代。code>if..then..else
(不删除该实现),因为它是此类函数的更标准定义。
reverse3 lst = 
    let aux lst acc = if null lst then acc else aux (tail lst) (head lst : acc) 
    in aux lst []