简体   繁体   English

Haskell中State的Functor / Applicative实例

[英]Functor / Applicative instances for State in Haskell

After reading (and skimming some sections of) Wadler's paper on monads, I decided to work through the paper more closely, defining functor and applicative instances for each of the monads he describes. 在阅读(并略读)Wadler关于monad的论文之后,我决定更仔细地研究这篇论文,为他描述的每个monad定义函子和应用实例。 Using the type synonym 使用类型同义词

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

Wadler uses to define the state monad, I have the following (using related names so I can define them with a newtype declaration later on). 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)

When I switch to using a type constructor in a newtype declaration, eg, 当我在newtype声明中切换到使用类型构造函数时,例如,

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

everything falls apart. 一切都崩溃了。 Everything is just a slight modification, for instance, 例如,一切都只是稍作修改

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))

however nothing runs in GHC due to the fact that the lambda expression is hidden inside that type constructor. 但是,由于lambda表达式隐藏在该类型构造函数中,因此GHC中没有任何内容运行。 Now the only solution I see is to define a function: 现在我看到的唯一解决方案是定义一个函数:

isntThisAnnoying s (S m) = m s

in order to bind s to 'st' and actually return a value, eg, 为了将s绑定到'st'并实际返回一个值,例如,

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

Is there another way to do this that doesn't use these auxiliary functions? 还有另一种不使用这些辅助功能的方法吗?

If you look here , you will see that they define it this way: 如果你看这里 ,你会看到他们这样定义:

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

so as to give the inner lambda a name. 以便给内在的lambda一个名字。

The usual way is to define newtype newtype S a = S {runState : State -> (a, State)} . 通常的方法是定义newtype newtype S a = S {runState : State -> (a, State)} Then instead of your isntThisAnnoying s (S m) you can write runState ts where t is the same as S m . 然后你可以编写runState ts而不是你的isntThisAnnoying s (S m) ,其中tS m相同。
You have to use a newtype because type synonyms cannot be typeclass instances. 您必须使用newtype因为类型同义词不能是类型类实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM