{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE UnicodeSyntax #-}

{-| This module contains types that represent the purity of a tree, which is
    either pure, impure, or IO (a special case of impure).
 -}
module LogicGrowsOnTrees.Parallel.Purity
    ( Purity(..)
    , io_purity
    ) where

import Control.Monad.IO.Class

import Data.Functor.Identity (Identity)

{-| The purity of a tree, which can be either 'Pure' (for pure trees) or
    'ImpureAtopIO' (for impure trees); the latter case is restricted to monads
    that are instances of 'MonadIO' and for which there exists a way to convert
    the monad into an IO action.

    The two kind arguments, @m@ and @n@, correspond to respectively the monad in
    on top of which the 'TreeT' monad transformer is stacked and the monad in
    which the worker will be run.
 -} 
data Purity (m :: *  *) (n :: *  *) where -- {{{
    Pure :: Purity Identity IO
    ImpureAtopIO :: MonadIO m  ( β. m β  IO β)  Purity m m

{-| The purity of trees in the IO monad. -}
io_purity :: Purity IO IO
io_purity = ImpureAtopIO id