Revolucent

Haskell State & Reader Arrows

Dec 11th, 2020
406
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {-# LANGUAGE Arrows #-}
  2. {-# LANGUAGE MultiParamTypeClasses #-}
  3. {-# LANGUAGE FlexibleContexts #-}
  4. {-# LANGUAGE FlexibleInstances #-}
  5. {-# LANGUAGE FunctionalDependencies #-}
  6. {-# LANGUAGE TupleSections #-}
  7.  
  8. {-
  9. I implemented State and Reader arrows (actually as Arrow Transformers) for
  10. educational purposes in order to understand arrows better.
  11.  
  12. Never use this code in a production environment. State and Reader arrows
  13. have already been defined. I reimplemented them purely for educational
  14. purposes.
  15. -}
  16.  
  17. module Educational where
  18.  
  19. import Prelude hiding ((.), id)
  20. import Control.Arrow
  21. import Control.Category
  22. import qualified Data.Bifunctor as Bi
  23.  
  24. newtype Identity b c = Identity { runIdentity :: b -> c }
  25.  
  26. instance Category Identity where
  27.     id = arr id
  28.     (Identity c) . (Identity b) = Identity $ c . b
  29.  
  30. instance Arrow Identity where
  31.     arr = Identity
  32.     first (Identity b) = Identity $ Bi.first b
  33.     second (Identity b) = Identity $ Bi.second b
  34.  
  35. class ArrowTrans t where
  36.     lift :: (Arrow a) => a b c -> t a b c
  37.  
  38. newtype StateT s a b c = StateT { runStateT :: a (b, s) (c, s) }
  39.  
  40. instance Category a => Category (StateT s a) where
  41.     id = StateT id
  42.     (StateT c) . (StateT b) = StateT $ c . b
  43.    
  44. instance Arrow a => Arrow (StateT s a) where
  45.    arr = StateT . first . arr
  46.    first (StateT f) = StateT $ arr (\((b, d), s) -> ((b, s), d)) >>> first f >>> arr (\((c, s), d) -> ((c, d), s))
  47.    second (StateT f) = StateT $ arr (\((d, b), s) -> (d, (b, s))) >>> second f >>> arr (\(d, (c, s)) -> ((d, c), s))
  48.  
  49. class Arrow a => ArrowState s a | a -> s where
  50.     gets :: a () s
  51.     puts :: a s s
  52.     modify :: (s -> s) -> a () s
  53.  
  54. instance Arrow a => ArrowState s (StateT s a) where
  55.     gets = StateT $ arr $ \(_, s) -> (s, s)
  56.     puts = StateT $ arr $ \(s, _) -> (s, s)
  57.     modify t = StateT $ arr $ \(_, s) -> let s' = t s in (s', s')
  58.  
  59. instance ArrowTrans (StateT s) where
  60.    lift = StateT . first
  61.  
  62. type State s b c = StateT s Identity b c
  63.  
  64. runState = runIdentity . runStateT
  65.  
  66. newtype ReaderT r a b c = ReaderT { runReaderT :: r -> a b c }
  67.  
  68. instance Category a => Category (ReaderT r a) where
  69.    id = ReaderT $ const id
  70.    (ReaderT c) . (ReaderT b) = ReaderT $ \r -> c r . b r
  71.  
  72. instance Arrow a => Arrow (ReaderT r a) where
  73.    arr = ReaderT . const . arr
  74.    first (ReaderT f) = ReaderT $ first . f
  75.    second (ReaderT f) = ReaderT $ second . f
  76.  
  77. class Arrow a => ArrowReader r a | a -> r where
  78.    ask :: a () r
  79.  
  80. instance Arrow a => ArrowReader r (ReaderT r a) where
  81.    ask = ReaderT $ arr . const
  82.  
  83. instance ArrowTrans (ReaderT r) where
  84.    lift = ReaderT . const
  85.  
  86. type Reader r b c = ReaderT r Identity b c
  87.  
  88. runReader :: Reader r b c -> r -> b -> c
  89. runReader a r = runIdentity (runReaderT a r)
  90.  
  91. zoo :: ArrowReader Int a => a Int Int
  92. zoo = arr ((),) >>> first ask >>> arr (uncurry (*))
  93.  
  94. foo :: ArrowState Int a => a Int Int
  95. foo = arr ((),) >>> first (modify (+3)) >>> second (arr (*2)) >>> arr (uncurry (+))
  96.  
  97. someFunc :: IO ()
  98. someFunc = print $ runState foo (7, 9)
  99.  
Add Comment
Please, Sign In to add comment