简体   繁体   English

反转 Haskell 中的列表的无限类型错误

[英]infinite type error reversing a list in Haskell

I'm trying to implement the reverse of a list:我正在尝试实现列表的反向:

myLast :: [a] -> a
myLast [] = error "No end for empty lists!"
myLast [x] = x
myLast (_:xs) = myLast xs

myReverse :: [a] -> [a]
myReverse (x:xs) = myLast xs + myReverse xs

but I get this error:但我收到此错误:

/workspaces/hask_exercises/exercises/src/Lib.hs:42:32: error:
    * Occurs check: cannot construct the infinite type: a ~ [a]
    * In the second argument of `(+)', namely `myReverse xs'
      In the expression: myLast xs + myReverse xs
      In an equation for `myReverse':
          myReverse (x : xs) = myLast xs + myReverse xs
    * Relevant bindings include
        xs :: [a] (bound at src/Lib.hs:42:14)
        x :: a (bound at src/Lib.hs:42:12)
        myReverse :: [a] -> [a] (bound at src/Lib.hs:41:1)
   |
42 | myReverse (x:xs) = myLast xs + myReverse xs
   |                                ^^^^^^^^^^^^

What does it mean that cannot construct the infinite type: a ~ [a] ? cannot construct the infinite type: a ~ [a]是什么意思? I get this error a lot and would like to understand what it means.我经常收到此错误,并想了解它的含义。

The (+):: Num a => a -> a -> a function adds two numbers (of the same type) together. (+):: Num a => a -> a -> a function 将两个数字(相同类型)加在一起。 So for example if a ~ Int , it will add two Int s together, but not an Int and a [Int] .因此,例如,如果a ~ Int ,它将两个Int加在一起,但不是Int[Int]

But even if the (+) operator for example would prepend an item to a list, it would still not reverse the list correctly: your function has no base case what to do for an empty list, and your recursive list does nothing with the first item x of the list (x:xs) .但是,即使(+)运算符例如将一个项目添加到列表中,它仍然无法正确反转列表:您的 function 没有基本情况如何处理空列表,并且您的递归列表与第一个无关列表中的项目x (x:xs)

A simple way to reverse:一个简单的反转方法:

myReverse :: [a] -> [a]
myReverse [] = []
myReverse (x:xs) = myReverse xs ++ [x]

But that is not efficient: appending two items will take linear time in the size of the left list.但这效率不高:添加两个项目将花费左列表大小的线性时间。 You can work with an accumulator: a parameter that you each time update when you make a recursive call.您可以使用累加器:每次进行递归调用时都会更新的参数。 This looks like:这看起来像:

myReverse :: [a] -> [a]
myReverse [] = go []
    where go ys (x:xs) = …
    where go ys [] = …

where filling in the parts are left as an exercise.填写部分留作练习。

You have你有

myLast :: [a] -> a 
myReverse :: [a] -> [a]

myReverse (x:xs) = myLast xs    +     myReverse xs
                   \___a___/          \____[a]___/

          (x:xs)  :: [a]
          ---------------
           x      ::  a
             xs   :: [a]                        xs :: [a]               
      myLast      :: [a] -> a         myReverse    :: [a] -> [a]
     -------------------------       ----------------------------
      myLast xs   ::        a         myReverse xs ::        [a]

myReverse (x:xs)                                   ::        [a]

but

> :t (+)
                               (+) :: Num a =>  a  ->  a  ->  a

which means that the type of the thing on the left of + and the type of the thing on the right must be the same.这意味着+左边的东西的类型和右边的东西的类型必须相同。

But they can't be: as we just saw above, in your code the first (of myLast xs ) is some type a , and the second (of myReverse xs ) is [a] the list of those same a s.但它们不可能是:正如我们刚刚在上面看到的,在您的代码中,第一个( myLast xs )是某种类型a ,第二个( myReverse xs )是[a]相同a列表

These two can't be the same, because it would mean这两个不能相同,因为这意味着

              a  ~  [a]             OK, this is given to us, then
                     a  ~ [a]       we can use it, so that
                 --------------
              a  ~ [[a]]            this must hold;
                     a  ~ [a]       we know this, then
                 --------------
             a  ~ [[[a]]]           this must also hold; and
                     a  ~ [a]       ........
                 --------------     ........
             a ~ [[[[a]]]]          ........
          .........................

and so on ad infinitum, thus making this a an "infinite" type.以此类推,无穷无尽,从而使其a “无限”类型。 Hence the error.因此错误。

You could fix it by replacing the + with您可以通过将+替换为

                              (+++) ::         a  ->  [a]  ->  [a]

and implementing it to do what you need it to do.并实施它来做你需要它做的事情。

You will also need to fix your off-by-one error whereby you completely ignore the first element in the received input, x .您还需要修复一个错误,即完全忽略接收到的输入中的第一个元素x

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM