在阅读了Wadler关于单子的论文(并浏览了其中的一些章节)之后,我决定更仔细地研究这篇论文,为他描述的每个单子定义函子和应用实例。使用类型同义词
type M a = State -> (a, State)
type State = Int
Wadler用来定义state 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声明中使用类型构造函数时,例如。,
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))
有没有其他不使用这些辅助功能的方法呢?