{-# OPTIONS
   -fglasgow-exts
   #-}

{-# LANGUAGE ScopedTypeVariables #-}

{-
Module      :  Control.Monad.IdentityX
Copyright   :  (c) Mark Snyder 2008.
License     :  BSD-style
Maintainer  :  Mark Snyder, marks@ittc.ku.edu
Stability   :  experimental
Portability :  portable
-}

module Control.Monad.IdentityX (
    IdentityX(..),
    runIdentityX,

    module Control.Monad,
    module Control.Monad.Fix,
    module Control.Monad.Index
   ) where

import Control.Monad
import Control.Monad.Fix

import Control.Monad.Index
import Control.Monad.Identity

data (Index ix) => IdentityX ix a = IdentityX ix a
runIdentityX :: (Index ix) => ix -> IdentityX ix a -> a
runIdentityX (_::ix) (IdentityX (_::ix) a) = a
--instead of... newtype Identity a = Identity { runIdentity :: a }

-- ---------------------------------------------------------------------------
-- Identity instances for Functor and Monad

instance (Index ix) => Functor (IdentityX ix) where
    fmap f m = IdentityX (getVal::ix) (f (runIdentityX (getVal::ix) m))

instance (Index ix) => Monad (IdentityX ix) where
    return a = IdentityX (getVal::ix) a
    m >>= k  = k (runIdentityX (getVal::ix) m)

instance (Index ix) => MonadFix (IdentityX ix) where
    mfix f = IdentityX (getVal::ix) (fix (runIdentityX (getVal::ix) . f))