簡體   English   中英

Haskell:模式匹配綁定運算符時,剛性類型變量錯誤

[英]Haskell: Rigid type variable error when pattern matching bind operator

我正在嘗試運行

newtype Test a = Test (Int, a)

instance Monad Test where
    Test (_, []) >>= k =
        k []
    Test (_, a) >>= k =
        k a
    return a =
        Test (0, a)

我得到錯誤:

Couldn't match expected type `a' with actual type `[t0]'
  `a' is a rigid type variable bound by
      the type signature for >>= :: Test a -> (a -> Test b) -> Test b
      at C:\Users\david.phillips\Documents\code\test.hs:4:5
In the pattern: []
In the pattern: (_, [])
In the pattern: Test (_, [])

當我嘗試使用case語句而不是>> =的2個版本時,出現類似的錯誤。

我對Haskell相當陌生,無法理解為什么這行不通。


編輯:對不起,這是一個不好的例子。 假設>> =的第一個定義給出了不同的輸出。

class Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  (>>) :: m a -> m b -> m b
  return :: a -> m a
  fail :: String -> m a

Monad實例通過類型變量a進行參數化。 實際上,您聲稱它不是,因為在該變量的位置,您在空列表構造函數[]上匹配了模式,表示“ a是某物的列表”。 例如的類型。 可以使用明確的量化來寫bind:

(>>=) :: forall a. ma -> (a -> mb) -> mb

您的定義可能對所有a無效。

除了Sarah的答案之外,您實際上可以省略特定的模式匹配,

 Test (_, []) >>= f = f []

是相同的

 Test (_, a) >>= f = f a

所以你真的可以這樣寫

 Test (_, a) >>= f = f a
 return a          = (0, a)

現在請記住,除了具有正確的類型之外,我們還應該擁有

 m >>= return    = m
 return a >>= f  = f a
 (a >>= b) >>= c = a >>= (\a' -> b a' >>= c)

不過這讓我擔心

 m = Test (1, 'c')
 m >>= return === return 'c' === (0, 'c') /== m

因此, return不再是一種身份,您將違反第一單子法則。 解決這個問題意味着return將必須保留元組的第一個元素,這是有問題的,因為我們實際上並沒有告訴它。

天真的,讓我們破壞函數返回的第一個元組元素。

 Test (a, b) >>= f = Test (a, snd (f b))

現在

 Test (1, 'c') >>= return == Test (1, snd (return 'c')) == Test (1, 'c')

但是我們仍然有麻煩

 let f a = Test (1, a)
 return a >>= f == Test (0, snd (f a)) == Test (0, a) /== f a

所以這里的竅門是做州立單子的工作

 newtype Test a = Test{ unTest :: Int -> (Int, a) }

 instance Monad Test where
   return a = Test $ \i -> (i, a)
   (Test m) >>= f = Test $ \i -> let (i', a) = m i
                    in unTest (f a) $ i'

確實滿足單子法則*。 幸運的是,這已經存在於Control.Monad.State

**模seq

擺脫第一個模式。 您正在嘗試為特定類型創建單獨的定義,但是您不能這樣做。 所有定義都必須針對所有類型a 如果你能違反的是,第一個模式是一樣的第二圖案,但有a必然[]所以只寫:

instance Monad Test where
    Test (_, a) >>= k =
        k a
    return a =
        Test (0, a)

Test (0, []) >>= k將匹配>>=模式,並變為k [] ,與您不必要的第一個模式完全相同。

暫無
暫無

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

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