2017-08-09 78 views
3

我寫單子的實現自定義類型:如何閱讀編譯器錯誤

data Sum a b = 
     First a 
    | Second b 
    deriving (Eq, Show) 

    instance Functor (Sum a) where 
    fmap _ (First x) = First x 
    fmap f (Second y) = Second (f y) 

    instance Applicative (Sum a) where 
    pure = Second 
    First x <*> _ = First x 
    _ <*> First x = First x 
    Second f <*> Second x = Second (f x) 

    instance Monad (Sum a) where 
    return = pure 
    (First a) >>= _ = First a 
    (Second a) >>= k = Second (k a) 

,我知道這是錯誤的。編譯器抱怨:

D:\haskell\chapter18\src\SumMonad.hs:39:24: error: 
    * Couldn't match type `b' with `Sum a b' 
     `b' is a rigid type variable bound by 
     the type signature for: 
      (>>=) :: forall a1 b. Sum a a1 -> (a1 -> Sum a b) -> Sum a b 
     at D:\haskell\chapter18\src\SumMonad.hs:38:15 
     Expected type: Sum a b 
     Actual type: Sum a (Sum a b) 
    * In the expression: Second (k a) 
     In an equation for `>>=': (Second a) >>= k = Second (k a) 
     In the instance declaration for `Monad (Sum a)' 
    * Relevant bindings include 
     k :: a1 -> Sum a b 
      (bound at D:\haskell\chapter18\src\SumMonad.hs:39:20) 
     (>>=) :: Sum a a1 -> (a1 -> Sum a b) -> Sum a b 
      (bound at D:\haskell\chapter18\src\SumMonad.hs:38:5) 
Failed, modules loaded: none. 

如何讀取編譯器錯誤?

回答

11
* Couldn't match type `b' with `Sum a b' 

翻譯:我(編譯)預期b,並得到了Sum a b代替。

`b' is a rigid type variable bound by 
    the type signature for: 
     (>>=) :: forall a1 b. Sum a a1 -> (a1 -> Sum a b) -> Sum a b 

翻譯:由於>>=簽名的類型變量b的具體類型值不能由您作爲選件,而是由你的來電者。你不能給我任何類型的值,並且期望b將你的表達式的類型作爲它的類型值(記住b是一個類型變量)。

Expected type: Sum a b 
    Actual type: Sum a (Sum a b) 

翻譯:爲了讓您更輕鬆,我給您提供了更多的上下文。我預計Sum a b,你遞給我一個Sum a (Sum a b)。現在,您已經可以看到,這個問題是在這裏大膽

 (>>=) :: forall a1 b. Sum a a1 -> (a1 -> Sum a b) ->Sum a b 

因爲這是你該函數的實現應該產生的值的類型。

* In the expression: Second (k a) 
    In an equation for `>>=': (Second a) >>= k = Second (k a) 
    In the instance declaration for `Monad (Sum a)' 

更多內容適合您。我(編譯)不喜歡錶達

Second (k a) 

方程

(Second a) >>= k = Second (k a) 

這裏,你可以推斷出,這Second (k a)的類型是Sum a (Sum a b),而不是Sum a b

而且更實用的訊息給你:

* Relevant bindings include 
    k :: a1 -> Sum a b 
     (bound at D:\haskell\chapter18\src\SumMonad.hs:39:20) 
    (>>=) :: Sum a a1 -> (a1 -> Sum a b) -> Sum a b 
     (bound at D:\haskell\chapter18\src\SumMonad.hs:38:5) 

翻譯:的k a結果已經是Sum a b,你看到了嗎?所以,如果你想到我的前(有希望有幫助的消息),Second (k a)將是Sum a (Sum a b)類型,這不是Sum a b,因爲我已經告訴過你。