module Acme.Smuggler
( inj, prj, smuggle, discover, mkId
) where
import Data.Typeable (Typeable)
import Data.Dynamic (toDyn, fromDynamic)
import System.IO.Unsafe (unsafePerformIO)
import Control.Exception (try, throw, evaluate)
-- | fancy name for smuggle
inj :: Typeable t => t -> a
inj = smuggle
-- | fancy name for discover
prj :: Typeable t => a -> Maybe t
prj = discover
smuggle :: Typeable t => t -> a
smuggle = throw . toDyn
discover :: Typeable t => a -> Maybe t
discover = either (fromDynamic) (const Nothing)
. unsafePerformIO
. try
. evaluate
-- | All functions of type (a -> a) are `id`.
-- This helper lets you create arbitrary `id` functions of
-- type (a -> a) which smuggle through a supplied value
mkId :: Typeable t => t -> (a -> a)
mkId t = const (smuggle t)