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

vla*_*378 2 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) : (head lst)
Run Code Online (Sandbox Code Playgroud)
-- Main.hs
import Helpers

main :: IO ()
main = putStrLn . reverse2 [2, 8, 7]
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

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)
Run Code Online (Sandbox Code Playgroud)

我怎么解决它?

jwo*_*der 8

reverse2 (tail lst)是类型[a],而head 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].


Dan*_*tin 5

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

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

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

reverse2 :: [t] -> [t]
reverse2 lst = if null lst
           then []
           else reverse2 (tail lst) : (head lst)
Run Code Online (Sandbox Code Playgroud)

这会将错误消息更改为:

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)
Run Code Online (Sandbox Code Playgroud)

好的,现在它说“我期望输入,t[t]在查看“的第一个参数时得到了类型:”。

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

Prelude> :t (:)
(:) :: a -> [a] -> [a]
Run Code Online (Sandbox Code Playgroud)

所以左边的参数 to:需要是一个单独的项目,右边的参数是一个列表。您在左侧使用列表,在右侧使用单个项目。

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

reverse2 :: [t] -> [t]
reverse2 lst = if null lst
           then []
           else reverse2 (tail lst) ++ [head lst]
Run Code Online (Sandbox Code Playgroud)

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