Skip to content

Instantly share code, notes, and snippets.

@munro
Last active August 29, 2015 14:20
Show Gist options
  • Save munro/6428a779567b95760ee5 to your computer and use it in GitHub Desktop.
Save munro/6428a779567b95760ee5 to your computer and use it in GitHub Desktop.
Monads with no built in functions or type classes
module MyState where
import Control.Monad.State.Lazy
data MyState s a = MyState { state :: s, carry :: a } deriving Show
data MyMonadState s a = MyMonadState (s -> (MyState s a))
myGet :: MyMonadState s s
myGet = MyMonadState (\s -> (MyState s s))
myPut :: s -> MyMonadState s ()
myPut s = MyMonadState (\_ -> (MyState s ()))
myNext :: MyMonadState s a -> MyMonadState s b -> MyMonadState s b
(MyMonadState l) `myNext` (MyMonadState r) =
MyMonadState (\state ->
(\(MyState s a) ->
r s) (l state))
myApply :: MyMonadState s a -> (a -> MyMonadState s b) -> MyMonadState s b
(MyMonadState monad) `myApply` m_return =
MyMonadState (\state_initial ->
(\(MyState s a) ->
((\(MyMonadState nt) -> nt) (m_return a)) s
) (monad state_initial))
-- {-# LANGUAGE ScopedTypeVariables #-}
-- (MyMonadState monad) `myApply` m_return = MyMonadState (\state_initial ->
-- let
-- monad_transform = monad state_initial :: MyState s a
-- state_a = (\(MyState s a) -> s) monad_transform :: s
-- acc_a = (\(MyState s a) -> a) monad_transform :: a
-- monad_next = m_return acc_a :: MyMonadState s b
-- monad_transform_next = (\(MyMonadState nt) -> nt) monad_next
-- state_final = monad_transform_next state_a :: MyState s b
-- in state_final)
myReturn :: a -> MyMonadState s a
myReturn a = MyMonadState (\s -> (MyState s a))
-- | myRunState
-- >>> myRunState (myGet `myApply` (\x -> myPut $ x * 2)) 123
-- MyState {state = 246, carry = ()}
-- >>> runState (get >>= (\x -> put $ x * 2)) 123
-- ((),246)
-- >>> myRunState myGet 123
-- MyState {state = 123, carry = 123}
-- >>> runState get 123
-- (123,123)
-- >>> myRunState (myReturn "ret") "state"
-- MyState {state = "state", carry = "ret"}
-- >>> runState (return "ret") "state"
-- ("ret","state")
-- >>> myRunState (myGet `myApply` (\x -> myPut $ x * 2) `myNext` myGet `myApply` (\x -> myPut $ x * 2)) 2
-- MyState {state = 8, carry = ()}
-- >>> runState (get >>= (\x -> put $ x * 2) >> get >>= (\x -> put $ x * 2)) 2
-- ((),8)
myRunState :: MyMonadState s b -> s -> MyState s b
myRunState (MyMonadState mt) s = mt s
-- | myExecState
-- >>> myExecState (myGet `myApply` (\x -> myPut $ x * 2) `myNext` myGet `myApply` (\x -> myPut $ x * 2)) 2
-- 8
-- >>> execState (get >>= (\x -> put $ x * 2) >> get >>= (\x -> put $ x * 2)) 2
-- 8
myExecState :: MyMonadState s b -> s -> s
myExecState m s = (\(MyState s _) -> s) (myRunState m s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment