了解monad实例

Asl*_*986 4 monads haskell

我有这个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)
Run Code Online (Sandbox Code Playgroud)

我是新来的单子,但我想我如何returnbind在一般情况下工作.

但在上面的例子中我有很多问题:

  1. Monad (State state)状态Monad的名字?它与它有什么关系newtype State ...
  2. return x = let f t = (t,x) in State f哪里t来自?

Lui*_*las 8

因此,通过这一点,你当然听说过的钻营部分应用程序:如果你有f :: a -> b -> cx :: a,然后f x :: b -> c.即,如果f是一个双参数函数并且x具有f第一个参数的类型,那么它f x是一个接受第二个参数并"完成"应用程序的函数.

好吧,在Haskell中同样适用于类型构造函数State.类型和类型构造函数有一种类型,类似于值的类型.非参数类型就像Integer有种类*; 单参数类型就像Maybe有种类* -> *; State善良* -> * -> *.

然后,State stateState类型构造函数的部分应用程序,并且具有类型* -> *. Monad是一个适用于那种类的类* -> *.所以,适用于我们的例子:

  1. instance Monad (Integer) where ...是禁止的,因为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
    -- ...
Run Code Online (Sandbox Code Playgroud)

看看如何m在这个类中声明使用:作为的一部分m am b,即作为带一个参数.因此,Haskell推断出这m是一种类型变量* -> *.

与此相比:

class Num a where
    (+) :: a -> a -> a
    (-) :: a -> a -> a
    -- ...
Run Code Online (Sandbox Code Playgroud)

这里的类型变量a不适用于其他类型变量 - 因此它必须是实物*.

所以严格来说,State不是一个单子; 它是一个两位类型的构造函数,当部分应用于一种类型时,它会为您提供一个monad.所以State state是一个monad,就像是State Integer,State [a]等等.人们经常说话松散,谈论State和monad类似的东西,但是你应该理解它是一个参数化的 monad-它是一个monad,它有一个内部类型参数,因此很多变种,该参数的类型不同.