Ok, così ho capito come implementare Reader
(e ReaderT
, non mostrato) utilizzando il pacchetto operational
:Come implementare Reader usando monadi gratuiti?
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
import Control.Monad.Operational
data ReaderI r a where
Ask :: ReaderI r r
type Reader r a = Program (ReaderI r) a
ask :: Reader r r
ask = singleton Ask
runReader :: forall r a. Reader r a -> r -> a
runReader = interpretWithMonad evalI
where evalI :: forall b. ReaderI r b -> (r -> b)
evalI Ask = id
Ma io non riesco a capire per la mia vita come fare questo con monadi gratuite (Sto usando il pacchetto free
di Edward Kmett). Il più vicino che ho ottenuto è questa, che capisco è barare (qualcosa su come ((->) r)
è già una monade):
import Control.Monad.Free
type Reader r a = Free ((->) r) a
ask :: Reader r r
ask = Free Pure
runReader :: Reader r a -> r -> a
runReader (Pure a) _ = a
runReader (Free k) r = runReader (k r) r
-- Or, more simply and tellingly:
--
-- > runReader = retract
Anche se questo non era stupido come ho il sospetto che sia, non è quello che ho voglio perché quello che voglio, in sostanza, è essere in grado di ispezionare un Reader
come dati ...
Non penso che si possa fare senza un tipo di funzione da qualche parte. –