Skip to content

Instantly share code, notes, and snippets.

@TerrorJack
Created August 29, 2017 13:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TerrorJack/89dd43778ce6657de091f6b22fffdd2e to your computer and use it in GitHub Desktop.
Save TerrorJack/89dd43778ce6657de091f6b22fffdd2e to your computer and use it in GitHub Desktop.
State monad done wrong
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module State where
import Control.Monad
import Control.Monad.Free.Church
import qualified Control.Monad.State.Class as MTL
import Data.Functor.Coyoneda
import Data.Kind
data State :: Type -> Type -> Type where
Get :: State s s
Put :: s -> State s ()
type StateF s = Coyoneda (State s)
type MonadState s m = MonadFree (StateF s) m
get :: MonadState s m => m s
get = liftF $ liftCoyoneda Get
put :: MonadState s m => s -> m ()
put = liftF . liftCoyoneda . Put
runState ::
forall s m a. (MTL.MonadState s m)
=> (forall m0. MonadState s m0 =>
m0 a)
-> m a
runState =
iterM
(join .
lowerCoyoneda .
hoistCoyoneda
(\case
Get -> MTL.get
(Put s) -> MTL.put s))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment