in-other-words-0.1.0.0: src/Control/Effect/Internal/Reflection.hs
{-# LANGUAGE AllowAmbiguousTypes, FunctionalDependencies #-}
module Control.Effect.Internal.Reflection
( Reifies (..)
, Tagged(..)
, unproxy
, reify
, reifyTagged
) where
import Unsafe.Coerce
import Data.Proxy
newtype Tagged s a = Tagged { getTagged :: a }
unproxy :: (Proxy s -> a) -> Tagged s a
unproxy f = Tagged (f Proxy)
{-# INLINE unproxy #-}
class Reifies s a | s -> a where
reflect :: a
data Skolem
newtype Magic a r = Magic (Reifies Skolem a => Tagged Skolem r)
reifyTagged :: forall a r. a -> (forall (s :: *). Reifies s a => Tagged s r) -> r
reifyTagged a k = unsafeCoerce (Magic k :: Magic a r) a
{-# INLINE reifyTagged #-}
reify :: forall a r. a -> (forall (s :: *) pr. (pr ~ Proxy, Reifies s a) => pr s -> r) -> r
reify a k = reifyTagged a (unproxy k)
{-# INLINE reify #-}