How do I implement Reader using free monads?

后端 未结 2 2019
醉梦人生
醉梦人生 2021-02-15 06:05

Ok, so I have figured out how to implement Reader (and ReaderT, not shown) using the operational package:

{-# LANGUAGE GADTs, ScopedTyp         


        
2条回答
  •  一向
    一向 (楼主)
    2021-02-15 06:42

    Well, I've been looking at this for 3 hours now, and I think I found something I like better. Since the Reader applicative is the same as the Reader monad, we can try an applicative version of operational:

    {-# LANGUAGE RankNTypes, GADTs, FlexibleInstances #-}
    
    import Control.Applicative
    
    data ProgramA instr a where
        Pure  :: a -> ProgramA r a
        Ap    :: ProgramA r (a -> b) -> ProgramA r a -> ProgramA r b
        Instr :: instr a -> ProgramA instr a
    
    infixl `Ap`
    
    instance Functor (ProgramA instr) where
        fmap f (Pure a) = Pure (f a)
        fmap f (ff `Ap` fa) = ((f .) <$> ff) `Ap` fa
        fmap f instr = Pure f `Ap` instr
    
    instance Applicative (ProgramA instr) where
        pure = Pure
        (<*>) = Ap
    
    interpretA :: Applicative f =>
                  (forall a. instr a -> f a)
               -> ProgramA instr a
               -> f a
    interpretA evalI (Pure a) = pure a
    interpretA evalI (ff `Ap` fa) = interpretA evalI ff <*> interpretA evalI fa
    interpretA evalI (Instr i) = evalI i
    
    data ReaderI r a where
        Ask :: ReaderI r r
    
    type Reader r a = ProgramA (ReaderI r) a
    
    ask :: Reader r r
    ask = Instr Ask
    
    runReader :: Reader r a -> r -> a
    runReader = interpretA (\Ask -> id)
    
    instance Monad (ProgramA (ReaderI r)) where
        return = pure
        ma >>= f = runReader <$> fmap f ma <*> ask
    

    The structure of a ProgramA (ReaderI r) a) can be inspected more straightforwardly than either Program (ReaderI r) a or Free ((->) r) a.

提交回复
热议问题