{-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DataKinds, PolyKinds #-} {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} {-# LANGUAGE Safe #-} -- Only for MemberU below, when emulating Monad Transformers {-# LANGUAGE FunctionalDependencies, UndecidableInstances #-} -- | Original work at . -- Open unions (type-indexed co-products) for extensible effects. -- This implementation relies on _closed_ type families added to GHC 7.8. It has -- NO overlapping instances module Data.OpenUnion.Internal.OpenUnion2( Union (..) , (:>) , Member , MemberU ) where import Data.OpenUnion.Internal.Base -- | Class Member is defined only for the sake of the interface compatibility -- with OpenUnion1. Generally, the closed type family Member' below could be -- used instead. -- -- The @`Member` t r@ specifies whether @t@ is present anywhere in the sum type -- @r@, where @t@ is some effectful type, e.g. @`Lift` `IO`@, @`State` Int`@. class (Member' t r ~ 'True) => Member (t :: * -> *) r instance (Member' t r ~ 'True) => Member t r type family Member' (t :: * -> *) r :: Bool where Member' t (t :> r) = 'True Member' t () = 'False Member' t (t' :> r) = Member' t r type family EQU (a :: k) (b :: k) :: Bool where EQU a a = 'True EQU a b = 'False -- | This class is used for emulating monad transformers class Member t r => MemberU (tag :: k -> * -> *) (t :: * -> *) r | tag r -> t instance (MemberU' (EQU t1 t2) tag t1 (t2 :> r)) => MemberU tag t1 (t2 :> r) class Member t r => MemberU' (f::Bool) (tag :: k -> * -> *) (t :: * -> *) r | tag r -> t instance MemberU' 'True tag (tag e) (tag e :> r) instance (Member' t (t' :> r) ~ 'True, MemberU tag t r) => MemberU' 'False tag t (t' :> r)