{-# 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()

newtype IdentityX ix a = IdentityX { runIdentityX' :: a }
mkIdentityX:: (Index ix) => ix -> a -> IdentityX ix a
mkIdentityX _ a = IdentityX a

runIdentityX :: (Index ix) => ix -> IdentityX ix a -> a
runIdentityX _ m = runIdentityX' m

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

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

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

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