Revolucent

Learning Monads & Monad Transformers

Aug 30th, 2019
478
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {-# LANGUAGE ExistentialQuantification #-}
  2. {-# LANGUAGE ExplicitForAll #-}
  3. {-# LANGUAGE FlexibleInstances #-}
  4. {-# LANGUAGE MultiParamTypeClasses #-}
  5. {-# LANGUAGE OverloadedStrings #-}
  6. {-# LANGUAGE ScopedTypeVariables #-}
  7. {-# LANGUAGE TupleSections #-}
  8.  
  9. {-
  10. This is an exercise in learning Haskell. I wrote these mostly in a clean-room fashion
  11. as a way to figure out how to do monads, monad transformers, a Reader monad (RT) and
  12. a state monad (ST).
  13. -}
  14.  
  15. module Main where
  16.  
  17. import Control.Applicative
  18. import Control.Monad.Identity
  19. import Control.Monad.IO.Class
  20. import Control.Monad.Reader
  21. import Control.Monad.State
  22. import Control.Monad.Trans
  23. import Data.Monoid
  24.  
  25. newtype RT r m a = RT { runRT :: r -> m a }
  26.  
  27. instance Functor m => Functor (RT r m) where
  28.     fmap f (RT a) = RT $ fmap f . a
  29.  
  30. instance Applicative m => Applicative (RT r m) where
  31.     pure = RT . const . pure
  32.     (RT f) <*> (RT a) = RT $ \r -> (f r) <*> (a r)
  33.  
  34. instance Monad m => Monad (RT r m) where
  35.     return = pure
  36.     (RT a) >>= f = RT $ \r -> do
  37.         a' <- a r
  38.        runRT (f a') r
  39.  
  40. instance MonadTrans (RT r) where
  41.     lift = RT . const
  42.  
  43. instance MonadIO m => MonadIO (RT r m) where
  44.     liftIO = lift . liftIO
  45.  
  46. instance Monad m => MonadReader r (RT r m) where
  47.     ask = RT return
  48.     local t (RT a) = RT $ \r -> a (t r)
  49.  
  50. type R r = RT r Identity
  51.  
  52. runR :: R r a -> r -> a
  53. runR a = runIdentity . runRT a
  54.  
  55. newtype ST s m a = ST { runST :: s -> m (a, s) }
  56.  
  57. evalST a = fst . runST a
  58. execST a = snd . runST a
  59.  
  60. instance Functor m => Functor (ST s m) where
  61.     fmap f (ST a) = ST $ fmap (\(a', s') -> (f a', s')) . a
  62.  
  63. instance Monad m => Applicative (ST s m) where
  64.     pure a = ST $ pure . (a,)
  65.     (ST f) <*> (ST a) = ST $ \s -> do
  66.         ~(f', s') <- f s
  67.         ~(a', s'') <- a s'
  68.         return $ (f' a', s'')
  69.  
  70. instance Monad m => Monad (ST s m) where
  71.     return = pure
  72.     (ST a) >>= f = ST $ \s -> do
  73.         ~(a', s') <- (a s)
  74.         runST (f a') s'
  75.  
  76. instance Monad m => MonadState s (ST s m) where
  77.     get = ST $ \s -> return (s, s)
  78.     put s = ST $ \_ -> return ((), s)
  79.  
  80. instance MonadTrans (ST s) where
  81.     lift a = ST $ \s -> a >>= return . (,s)
  82.  
  83. instance MonadIO m => MonadIO (ST s m) where
  84.     liftIO = lift . liftIO
  85.  
  86. type S s = ST s Identity
  87.  
  88. runS :: S s a -> s -> (a, s)
  89. runS a = runIdentity . runST a
  90.  
  91. evalS a = fst . runS a
  92. execS a = snd . runS a
  93.  
  94. type RS a = RT a (S a) a
  95.  
  96. runRS :: Int -> Int -> RS Int -> (Int, Int)
  97. runRS r s a = runS (runRT a r) s
  98.  
  99. evalRS r s a = fst $ runRS r s a
  100. execRS r s a = snd $ runRS r s a
  101.  
  102. x :: Int -> RT Int (S Int) Int
  103. x n = do
  104.     r <- ask
  105.     s <- lift $ do
  106.         modify (+n)
  107.         get
  108.     return $ (n * n) + (r * s)
  109.  
  110. main = print $ runS (runRT (liftA2 (+) (x 2) (x 1)) 2) 1
Add Comment
Please, Sign In to add comment