{-# LANGUAGE RoleAnnotations, StandaloneDeriving, FlexibleContexts, UndecidableInstances, GADTs, TypeFamilies #-} import Data.Coerce (Coercible, coerce) import Data.Monoid (mempty, First(First), Last()) newtype Age = Age Int deriving Show newtype Foo = Foo Age deriving Show newtype Bar = Bar Age deriving Show newtype Baz = Baz Bar deriving Show type role Map nominal representational data Map a b = Map a b deriving Show -- Higher kinded coercions (#8541) newtype List a = List [a] deriving Show data T f = T (f Int) -- It should be possible to coerce _under_ undersaturated newtypes newtype NonEtad a b = NonEtad (Either b a) deriving Show -- It should be possible to coerce recursive newtypes, in some situations -- (#8503) newtype Fix f = Fix (f (Fix f)) deriving instance Show (f (Fix f)) => Show (Fix f) -- Later, however, this stopped working (#9117) -- newtype FixEither a = FixEither (Either a (FixEither a)) deriving Show -- This ensures that explicitly given constraints are consulted, even -- at higher depths -- This stopped working with the fix to #9117 --data Oracle where Oracle :: Coercible (Fix (Either Age)) -- (Fix (Either Int)) => Oracle --foo :: Oracle -> Either Age (Fix (Either Age)) -> Fix (Either Int) --foo Oracle = coerce -- This ensures that Coercible looks into newtype instances (#8548) data family Fam k newtype instance Fam Int = FamInt Bool deriving Show main = do print (coerce $ one :: Age) print (coerce $ age :: Int) print (coerce $ Baz (Bar age) :: Foo) print (coerce (id::Bar->Bar) age :: Foo) print (coerce Baz age :: Foo) print (coerce $ (Age 1, Foo age) :: (Baz, Baz)) print (coerce $ Map one one :: Map Int Age) print (coerce $ Just one :: First Int) print (coerce $ (mempty :: Last Age) :: Last Int) printT (coerce $ (T (Left age) :: T (Either Age)) :: T (Either Int)) printT (coerce $ (T (Left one) :: T (Either Int)) :: T (Either Age)) printT (coerce $ (T [one] :: T []) :: T List) printT (coerce $ (T (List [one]) :: T List) :: T []) printT (coerce $ (T (NonEtad (Right age)) :: T (NonEtad Age)) :: T (NonEtad Int)) print (coerce $ (Fix (Left ()) :: Fix (Either ())) :: Either () (Fix (Either ()))) print (coerce $ (Left () :: Either () (Fix (Either ()))) :: Fix (Either ())) -- print (coerce $ (FixEither (Left age) :: FixEither Age) -- :: Either Int (FixEither Int)) -- print (coerce $ (Left one :: Either Int (FixEither Age)) :: FixEither Age) print (coerce $ True :: Fam Int) print (coerce $ FamInt True :: Bool) -- foo `seq` return () where one = 1 :: Int age = Age one printT (T x) = print x