Funk / Applicative在Haskell中的状态实例

在阅读Wadler关于monad的论文(并略读了部分内容)之后,我决定更仔细地研读论文,为他描述的每个monad定义仿函数和应用实例。 使用类型同义词

type M a = State -> (a, State)
type State = Int

Wadler用来定义状态monad,我有以下(使用相关的名称,以便我可以在稍后用newtype声明来定义它们)。

fmap' :: (a -> b) -> M a -> M b
fmap' f m = st -> let (a, s) = m st in (f a, s)

pure' :: a -> M a
pure' a = st -> (a, st)

(<@>) :: M (a -> b) -> M a -> M b
sf <@> sv = st -> let (f, st1) = sf st
                       (a, st2) = sv st1
                    in (f a, st2)

return' :: a -> M a
return' a = pure' a

bind :: M a -> (a -> M b) -> M b
m `bind` f = st -> let (a, st1) = m st
                        (b, st2) = f a st1
                     in (b, st2)

当我在新类型声明中切换到使用类型构造函数时,例如,

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

一切都崩溃了。 例如,一切都只是一个小小的修改,

instance Functor S where
 fmap f (S m) = S (st -> let (a, s) = m st in (f a, s)) 

instance Applicative S where
 pure a = S (st -> (a, st))

然而,由于lambda表达式隐藏在该类型的构造函数中,因此GHC中没有运行。 现在我看到的唯一解决方案是定义一个函数:

isntThisAnnoying s (S m) = m s

为了将s绑定到'st'并实际返回一个值,例如,

fmap f m = S (st -> let (a, s) = isntThisAnnoying st m in (f a, s))

有没有另外一种方法来做到这一点,而不使用这些辅助功能?


如果你看这里,你会看到他们这样定义它:

newtype State s a = State { runState :: (s -> (a,s)) }

以便给内部lambda一个名字。


通常的方法是定义newtype newtype S a = S {runState : State -> (a, State)} 。 那么不用你的isntThisAnnoying s (S m)你可以编写runState ts ,其中tS m相同。
你必须使用一个newtype因为类型同义词不能是类型类的实例。

链接地址: http://www.djcxy.com/p/33215.html

上一篇: Functor / Applicative instances for State in Haskell

下一篇: Haskell: print TextEncoding