Domanda

Dopo aver letto (e sfiorando alcune sezioni) della carta di Wadler su monadi, ho deciso di lavorare attraverso la carta più da vicino, la definizione di funtore e le istanze applicative per ciascuna delle monadi che descrive. Utilizzando il tipo sinonimo

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

Wadler utilizza per definire la monade stato, ho il seguente (utilizzando nomi correlati modo che io possa definire con una dichiarazione newtype più tardi).

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)

Quando si passa ad usare un costruttore di tipo in una dichiarazione newtype, per es.,

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

tutto cade a pezzi. Tutto è solo una leggera modifica, per esempio,

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

tuttavia corre niente in GHC a causa del fatto che l'espressione lambda è nascosto all'interno di quel tipo di costruzione. Ora l'unica soluzione che vedo è quello di definire una funzione:

isntThisAnnoying s (S m) = m s

al fine di impegnare s per 'st' ed effettivamente restituire un valore, per es.,

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

C'è un altro modo per farlo che non utilizza queste funzioni ausiliarie?

È stato utile?

Soluzione

Se si guarda qui , vedrete che essi definiscono in questo modo:

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

in modo da dare il lambda interno un nome.

Altri suggerimenti

Il modo usuale è quello di definire newtype newtype S a = S {runState : State -> (a, State)}. Poi al posto del tuo isntThisAnnoying s (S m) si può scrivere runState t s dove t è lo stesso di S m.
Devi usare un newtype perché Sinonimi di tipo non può essere typeclass casi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top