Pregunta

Después de leer (y rozando algunas secciones de) papel de Wadler en mónadas, decidí trabajar a través del papel más de cerca, definiendo funtor y casos aplicativos para cada una de las mónadas que describe. Utilizando el tipo de sinónimos

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

Wadler utiliza para definir la mónada estado, he lo siguiente (utilizando nombres relacionados para que pueda definirlos con una declaración newtype más adelante).

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)

Cuando cambio al uso de un constructor de tipos en una declaración newtype, por ejemplo.,

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

todo se desmorona. Todo es simplemente una ligera modificación, por ejemplo,

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

Sin embargo, nada se ejecuta en GHC debido al hecho de que la expresión lambda se oculta dentro de ese tipo constructor. Ahora, la única solución que veo es definir una función:

isntThisAnnoying s (S m) = m s

a fin de obligar a s 'st' y, de hecho devolver un valor, por ejemplo.,

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

¿Hay otra manera de hacer esto que no utilice estas funciones auxiliares?

¿Fue útil?

Solución

Si nos fijamos aquí , se verá que lo definen así:

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

a fin de dar la lambda interior un nombre.

Otros consejos

La forma más habitual es definir newtype newtype S a = S {runState : State -> (a, State)}. A continuación, en lugar de su isntThisAnnoying s (S m) puede escribir runState t s donde t es la misma que S m.
Usted tiene que utilizar un tipo newtype porque sinónimos no pueden ser clase de tipos casos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top