[–]bss032 points2 years ago* (last edited 2 years ago)
(4 children)
I put this together this evening.
{-# language GADTs #-}
{-# language RankNTypes #-}
import Data.Functor.Const
-- The GADT
data AGADT a where
I :: [Integer] -> AGADT Integer
S :: String -> AGADT String
type Scott_GADT a = forall fr. ([Integer] -> fr Integer) -> (String -> fr String) -> fr a
f :: AGADT a -> String
f (I x) = show x
f (S x) = x
f' :: Scott_GADT a -> String
f' x = getConst $ x (Const . show) Const
-- The Existential
data AnyGADT = forall a. MkAnyGADT (AGADT a)
type Scott_Any =
forall r.
(forall a. (forall fr. ([Integer] -> fr Integer) -> (String -> fr String) -> fr a) -> r) ->
r
g :: String -> AnyGADT
g "foo" = MkAnyGADT (I [42])
g "bar" = MkAnyGADT (I [69])
g x = MkAnyGADT (S x)
g' :: String -> Scott_Any
g' "foo" x = x (\i _s -> i [42])
g' "bar" x = x (\i _s -> i [69])
g' s x = x (\_i s' -> s' s)
main = interact (unlines . fmap x . lines)
where
x s = case g s of { MkAnyGADT x -> f x }
y s = g' s f'
You can swap out x for y to see the behavior is the same.
You can drop the GADT pragma, GADT definition, f, existential, g, and x (but keep all the Scott versions, includeing y) to reveal code that works "simply" with RankNTypes.
Higher-rank types and parametricity is quite powerful.
BTW, this isn't new / doesn't require the bleeding edge compiler. I'm on "The Glorious Glasgow Haskell Compilation System, version 9.0.2" from the Debian repositories.
I put this together this evening.
You can swap out
x
fory
to see the behavior is the same.You can drop the
GADT
pragma, GADT definition,f
, existential,g
, andx
(but keep all the Scott versions, includeingy
) to reveal code that works "simply" withRankNTypes
.Higher-rank types and parametricity is quite powerful.
BTW, this isn't new / doesn't require the bleeding edge compiler. I'm on "The Glorious Glasgow Haskell Compilation System, version 9.0.2" from the Debian repositories.