{-# 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,
    mkIdentityX,

    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
newtype IdentityX ix a = IdentityX { runIdentityX :: a }
mkIdentityX:: (Index ix) => ix -> a -> IdentityX ix a
mkIdentityX _ a = IdentityX a

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

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

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

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