Skip to content

Instantly share code, notes, and snippets.

@snipsnipsnip
Last active August 24, 2019 15:24
Show Gist options
  • Save snipsnipsnip/112950 to your computer and use it in GitHub Desktop.
Save snipsnipsnip/112950 to your computer and use it in GitHub Desktop.
Variable in monad
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, FunctionalDependencies #-}
module Var
( MonadVar (..)
, module Control.Monad.Trans
) where
import Control.Monad.Error
import Control.Monad.State
import Control.Monad.Reader
import Control.Monad.Writer
import Control.Monad.Trans
import Data.IORef
class Monad m => MonadVar v m | m -> v where
var :: a -> m (v a)
ref :: v a -> m a
(@=) :: v a -> a -> m ()
-- utils
refs :: v a -> (a -> b) -> m b
refs v f = liftM f $ ref v
(=~) :: v a -> (a -> a) -> m ()
v =~ f = refs v f >>= (v @=)
infixr 0 @=, =~
instance MonadVar IORef IO where
var = newIORef
ref = readIORef
(@=) = writeIORef
(=~) = modifyIORef
instance (MonadVar v m) => MonadVar v (ReaderT s m) where
var = lift . var
ref = lift . ref
v @= x = lift $ v @= x
instance (MonadVar v m) => MonadVar v (StateT s m) where
var = lift . var
ref = lift . ref
v @= x = lift $ v @= x
instance (MonadVar v m, Monoid w) => MonadVar v (WriterT w m) where
var = lift . var
ref = lift . ref
v @= x = lift $ v @= x
instance (MonadVar v m, Error e) => MonadVar v (ErrorT e m) where
var = lift . var
ref = lift . ref
v @= x = lift $ v @= x
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment