2012-06-05 29 views
4

我有這樣的Haskell代碼部分:瞭解一個單子實例

newtype State st a = State (st -> (st, a)) 

instance Monad (State state) where 
    return x = let f t = (t,x) in State f 

    State f >>= g = State (\oldstate -> 
       let {(newstate, val) = f oldstate; 
        State f'= g val} 
       in f' newstate) 

我是新來的單子,但我想我returnbind作品在一般情況下如何。

但是在上面的例子中,我有很多問題:

  1. Monad (State state)是國家單子的名字?它怎麼樣 與newtype State ...有關?
  2. in return x = let f t = (t,x) in State ft從哪裏來?

回答

8

因此,通過這一點,你當然聽說過討好部分應用程序的:如果你有f :: a -> b -> cx :: a,然後f x :: b -> c。即,如果f是雙參數函數,並且x具有f的第一個參數類型,則f x是接受第二個參數並「完成」應用程序的函數。

那麼,在Haskell中,同樣的事情適用於類型構造函數,如State。類型和類型構造函數有一個種類,這類似於值的類型。像Integer這樣的非參數類型具有種類*;像Maybe這樣的單參數類型具有種類* -> *; State有種類* -> * -> *

然後,State stateState類型構造函數的部分應用程序,並且具有種類* -> *Monad是適用於種類* -> *的類。因此,應用到我們的例子:

  1. ​​是被禁止的,因爲Integer有種*
  2. instance Monad (Maybe) where ...被允許,因爲Maybe有種類* -> *
  3. instance Monad (State) where ...被禁止,因爲State有種類* -> * -> *
  4. instance Monad (State st) where ...被允許,因爲State st有種類* -> *

我們怎麼知道Monad適用於種類* -> *?我們可以從類聲明來推斷:

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

m是如何在這個類聲明中使用:作爲m am b,即一部分,因爲帶一個參數。因此,Haskell推斷m是一種類型變量* -> *

比較此:

class Num a where 
    (+) :: a -> a -> a 
    (-) :: a -> a -> a 
    -- ... 

這裏類型變量a不被施加到其它類型的變量,因此它必須是樣*

嚴格地說,State不是單子;它是一個兩位類型的構造函數,當部分應用於一種類型時,會給你一個monad。所以State state是一個單子,因爲是State IntegerState [a]等人也常說鬆散和State通話和類似事情的單子,雖然,但你應該明白這是一個參數化單子,它是有一個內部類型單子參數以及因此參數類型不同的許多變體。

1
  1. State是單子的類型,instance Monad (State state)被宣告State state(其中state是可以被設置爲任何其它類型*類型變量)是的Monad一個實例。 newtype StateState類型的定義。
  2. let f t = (t, x)定義了一個函數,其參數名爲t

*從技術上講,state*類型的變量,但不用擔心這一點。