{-# LANGUAGE CPP #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
module Distribution.Compat.Newtype (
Newtype (..),
ala,
alaf,
pack',
unpack',
) where
import Data.Functor.Identity (Identity (..))
import Data.Monoid (Sum (..), Product (..), Endo (..))
#if MIN_VERSION_base(4,7,0)
import Data.Coerce (coerce, Coercible)
#else
import Unsafe.Coerce (unsafeCoerce)
#endif
class Newtype o n | n -> o where
pack :: o -> n
#if MIN_VERSION_base(4,7,0)
default pack :: Coercible o n => o -> n
pack = coerce
#else
default pack :: o -> n
pack = unsafeCoerce
#endif
unpack :: n -> o
#if MIN_VERSION_base(4,7,0)
default unpack :: Coercible n o => n -> o
unpack = coerce
#else
default unpack :: n -> o
unpack = unsafeCoerce
#endif
instance Newtype a (Identity a)
instance Newtype a (Sum a)
instance Newtype a (Product a)
instance Newtype (a -> a) (Endo a)
ala :: (Newtype o n, Newtype o' n') => (o -> n) -> ((o -> n) -> b -> n') -> (b -> o')
ala pa hof = alaf pa hof id
alaf :: (Newtype o n, Newtype o' n') => (o -> n) -> ((a -> n) -> b -> n') -> (a -> o) -> (b -> o')
alaf _ hof f = unpack . hof (pack . f)
pack' :: Newtype o n => (o -> n) -> o -> n
pack' _ = pack
unpack' :: Newtype o n => (o -> n) -> n -> o
unpack' _ = unpack