Después de leer (y pasar algunas secciones de) el documento de Wadler sobre mónadas, decidí trabajar más detenidamente en el documento, definiendo el funtor y las instancias aplicativas para cada una de las mónadas que describe. Que utiliza el sinónimo de tipoFunctor/Instancias aplicables para estado en Haskell
type M a = State -> (a, State)
type State = Int
Wadler utiliza para definir la mónada estado, tengo los siguientes (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 s a 'st' y en realidad 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 usa estas funciones auxiliares?
Lo que también significa 'runState = flip isntThisAnnoying'. – kennytm
Bien, entonces, aunque todavía se necesita una función auxiliar, podría simplemente definir el tipo usando un registro, obteniendo la función de forma gratuita. Lo que estás diciendo, entonces, es que no hay forma de evitar el uso de funciones como 'runState' o 'run'. Gracias. – danportin
Si le duele pensar que es una función, piense en ello como un acceso de campo de estructura. :-) –