-------------------------------------------------------------------------------------------
-- |
  Module 	 : Control .  . Hyper
  Copyright 	 : 2008  
-- License	: BSD
--
  Maintainer 	 :   <  >
-- Stability	: experimental
-- Portability	: non-portable (functional-dependencies)
--
-- Based on the construction of hyperfunctions as parameterized monads in 
-- </~pjohann/f14-ghani.pdf>
-------------------------------------------------------------------------------------------

module Control.Monad.Hyper 
	( ContraFunctor(..)
	, Hyper
	, Hyp
	, PHyper(..)
	) where

import Control.Category.Hask
import Control.Functor
import Control.Functor.Fix
import Control.Functor.Contra
import Control.Monad.Instances
import Control.Monad.Parameterized

newtype PHyper h a b = PHyper { runPHyper :: h b -> a } 

instance PFunctor (PHyper h) Hask Hask where
	first f h = PHyper (f . runPHyper h)

instance ContraFunctor h => QFunctor (PHyper h) Hask Hask where
	second g h = PHyper (runPHyper h . contramap g)

instance ContraFunctor h => Bifunctor (PHyper h) Hask Hask Hask where
	bimap f g h = PHyper (f . runPHyper h . contramap g)

instance ContraFunctor h => PPointed (PHyper h) where
	preturn = PHyper . const

instance ContraFunctor h => PApplicative (PHyper h) where
	pap = papPMonad

instance ContraFunctor h => PMonad (PHyper h) where
	pbind k (PHyper h) = PHyper (k . h >>= runPHyper)

-- | A generic recursive hyperfunction-like combinator
type Hyper h a = Fix (PHyper h)

-- | Traditional Hyper functions
type Hyp e a = Hyper (ContraF e) a

-----------------------------------------------------------------------------------------
 |
 License	: BSD

 Stability	: experimental
 Portability	: non-portable (functional-dependencies)

 Based on the construction of hyperfunctions as parameterized monads in 
 </~pjohann/f14-ghani.pdf>
-----------------------------------------------------------------------------------------
 | A generic recursive hyperfunction-like combinator
 | Traditional Hyper functions
  Module 	 : Control .  . Hyper
  Copyright 	 : 2008  
  Maintainer 	 :   <  >

module Control.Monad.Hyper 
	( ContraFunctor(..)
	, Hyper
	, Hyp
	, PHyper(..)
	) where

import Control.Category.Hask
import Control.Functor
import Control.Functor.Fix
import Control.Functor.Contra
import Control.Monad.Instances
import Control.Monad.Parameterized

newtype PHyper h a b = PHyper { runPHyper :: h b -> a } 

instance PFunctor (PHyper h) Hask Hask where
	first f h = PHyper (f . runPHyper h)

instance ContraFunctor h => QFunctor (PHyper h) Hask Hask where
	second g h = PHyper (runPHyper h . contramap g)

instance ContraFunctor h => Bifunctor (PHyper h) Hask Hask Hask where
	bimap f g h = PHyper (f . runPHyper h . contramap g)

instance ContraFunctor h => PPointed (PHyper h) where
	preturn = PHyper . const

instance ContraFunctor h => PApplicative (PHyper h) where
	pap = papPMonad

instance ContraFunctor h => PMonad (PHyper h) where
	pbind k (PHyper h) = PHyper (k . h >>= runPHyper)

type Hyper h a = Fix (PHyper h)

type Hyp e a = Hyper (ContraF e) a
