{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-} module Control.IxMonad.Reader (HNil'(..), HCons'(..), ask, Split(..)) where import Control.IxMonad import Control.IxMonad.Cond import Data.HList hiding (Monad(..)) import Prelude hiding (Monad(..)) instance IxMonad (->) where type Inv (->) s t = Split s t type Unit (->) = HNil' type Plus (->) s t = Append s t return x = \HNil' -> x e >>= k = \xs -> let (s, t) = split xs in (k (e s)) t ask :: (HCons' a HNil') -> a ask = \(HCons' a HNil') -> a -- Type-level append, and dual operations for split class Split s t where type Append s t split :: Append s t -> (s, t) instance Split HNil' t where type Append HNil' t = t split t = (HNil', t) instance Split xs ys => Split (HCons' x xs) ys where type Append (HCons' x xs) ys = HCons' x (Append xs ys) split (HCons' x xs) = let (xs', ys') = split xs in (HCons' x xs', ys') -- Conditionals instance Cond (->) where type AltInv (->) s t = Split s t type Alt (->) s t = Append s t ifM True x y = \rs -> let (r, s) = split rs _ = y s in x r ifM False x y = \rs -> let (r, s) = split rs _ = x r in y s