簡體   English   中英

反轉 Haskell 中的列表的無限類型錯誤

[英]infinite type error reversing a list in Haskell

我正在嘗試實現列表的反向:

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

但我收到此錯誤:

/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
   |                                ^^^^^^^^^^^^

cannot construct the infinite type: a ~ [a]是什么意思? 我經常收到此錯誤,並想了解它的含義。

(+):: Num a => a -> a -> a function 將兩個數字(相同類型)加在一起。 因此,例如,如果a ~ Int ,它將兩個Int加在一起,但不是Int[Int]

但是,即使(+)運算符例如將一個項目添加到列表中,它仍然無法正確反轉列表:您的 function 沒有基本情況如何處理空列表,並且您的遞歸列表與第一個無關列表中的項目x (x:xs)

一個簡單的反轉方法:

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

但這效率不高:添加兩個項目將花費左列表大小的線性時間。 您可以使用累加器:每次進行遞歸調用時都會更新的參數。 這看起來像:

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

填寫部分留作練習。

你有

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]

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

這意味着+左邊的東西的類型和右邊的東西的類型必須相同。

但它們不可能是:正如我們剛剛在上面看到的,在您的代碼中,第一個( myLast xs )是某種類型a ,第二個( myReverse xs )是[a]相同a列表

這兩個不能相同,因為這意味着

              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]]]]          ........
          .........................

以此類推,無窮無盡,從而使其a “無限”類型。 因此錯誤。

您可以通過將+替換為

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

並實施它來做你需要它做的事情。

您還需要修復一個錯誤,即完全忽略接收到的輸入中的第一個元素x

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM