typelet-0.1.0.0: test/Test/WithoutPlugin.hs
{-# OPTIONS_GHC -ddump-ds-preopt -ddump-ds -ddump-simpl -ddump-to-file #-}
-- | Show that we do not /need/ the plugin; it's just more convenient.
module Test.WithoutPlugin where
import Data.Kind
import Data.Type.Equality
import Test.Infra
data LetT :: a -> Type where
LetT :: (b :~: a) -> LetT a
-- The NOINLINE pragma is essential, otherwise the inliner just undoes our work
{-# NOINLINE letT #-}
letT :: LetT a
letT = LetT Refl
castSingleLet :: Int -> Int
castSingleLet x =
case letT of { LetT (p :: b :~: Int) ->
let x' :: b
x' = case p of Refl -> x
in case p of Refl -> x'
}
-- | Correct version (albeit somewhat clunky)
hlist1 :: HList '[A, B, C]
hlist1 =
case letT of { LetT (p2 :: r2 :~: (C : '[])) ->
case letT of { LetT (p1 :: r1 :~: (B : r2 )) ->
case letT of { LetT (p0 :: r0 :~: (A : r1 )) ->
let xs2 :: HList r2
xs1 :: HList r1
xs0 :: HList r0
xs2 = case p2 of Refl -> HCons C HNil
xs1 = case p1 of Refl -> HCons B xs2
xs0 = case p0 of Refl -> HCons A xs1
in case p0 of { Refl ->
case p1 of { Refl ->
case p2 of { Refl ->
xs0
}}}
}}}
-- | Unpacking the equalities in the wrong order (leading to quadratic code)
hlist2 :: HList '[A, B, C]
hlist2 =
case letT of { LetT (p2 :: r2 :~: (C : '[])) ->
case letT of { LetT (p1 :: r1 :~: (B : r2 )) ->
case letT of { LetT (p0 :: r0 :~: (A : r1 )) ->
let xs2 :: HList r2
xs1 :: HList r1
xs0 :: HList r0
xs2 = case p2 of Refl -> HCons C HNil
xs1 = case p1 of Refl -> HCons B xs2
xs0 = case p0 of Refl -> HCons A xs1
in case p2 of { Refl ->
case p1 of { Refl ->
case p0 of { Refl ->
xs0
}}}
}}}
-- | Just for completeness, a version where /we/ construct equality proofs
hlist3 :: HList '[A, B, C]
hlist3 =
case letT of { LetT (p2 :: r2 :~: (C : '[])) ->
case letT of { LetT (p1 :: r1 :~: (B : r2 )) ->
case letT of { LetT (p0 :: r0 :~: (A : r1 )) ->
let xs2 :: HList r2
xs1 :: HList r1
xs0 :: HList r0
xs2 = castWith (cong (sym p2)) (HCons C HNil)
xs1 = castWith (cong (sym p1)) (HCons B xs2)
xs0 = castWith (cong (sym p0)) (HCons A xs1)
in castWith (cong (comp p0 (comp p1 p2))) xs0
}}}
{-------------------------------------------------------------------------------
Auxiliary
-------------------------------------------------------------------------------}
cong :: (a :~: b) -> f a :~: f b
cong Refl = Refl
comp :: (a :~: x : b) -> b :~: c -> a :~: x : c
comp Refl Refl = Refl