packages feed

overloaded-0.2.1: test/IxMonad.hs

{-# LANGUAGE AllowAmbiguousTypes   #-}
{-# LANGUAGE DataKinds             #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE GADTs                 #-}
{-# LANGUAGE KindSignatures        #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances  #-}
module IxMonad where

import Data.Functor.Identity (Identity (..))
import Data.Kind             (Type)
import Overloaded.Do

-------------------------------------------------------------------------------
-- Class
-------------------------------------------------------------------------------

class IxMonad m where
    ipure :: a -> m i i a
    (>>>=) :: m i j a -> (a -> m j k b) -> m i k b

infixl 4 >>>=

-------------------------------------------------------------------------------
-- Indexed State
-------------------------------------------------------------------------------

newtype IxStateT m i j a = IxStateT { runIxStateT :: i -> m (a, j) }

instance Monad m => IxMonad (IxStateT m) where
    ipure x = IxStateT $ \i -> pure (x, i)

    m >>>= k = IxStateT $ \s0 -> do
        (x, s1) <- runIxStateT m s0
        runIxStateT (k x) s1

ixmodify :: Applicative m => (i -> j) -> IxStateT m i j ()
ixmodify f = IxStateT $ \i -> pure ((), f i)

execIxState :: IxStateT Identity i j a -> i -> j
execIxState m i = snd (runIdentity (runIxStateT m i))

-------------------------------------------------------------------------------
-- Overloading
-------------------------------------------------------------------------------

class IxMonad' (method :: DoMethod) (ty :: Type) where
    ixmonad :: ty

instance (ty ~ (a -> m i i a),                         IxMonad m) => IxMonad' 'Pure ty where ixmonad = ipure
instance (ty ~ (m i j a -> m j k b -> m i k b),        IxMonad m) => IxMonad' 'Then ty where ixmonad = \x y -> x >>>= \_ -> y
instance (ty ~ (m i j a -> (a -> m j k b) -> m i k b), IxMonad m) => IxMonad' 'Bind ty where ixmonad = (>>>=)