Skip to content

Instantly share code, notes, and snippets.

@damhiya
Last active June 13, 2026 14:06
Show Gist options
  • Select an option

  • Save damhiya/5dad66207d6d4667876c10908f121add to your computer and use it in GitHub Desktop.

Select an option

Save damhiya/5dad66207d6d4667876c10908f121add to your computer and use it in GitHub Desktop.
Mimicking GADTs using RankNTypes, ExistentialQuantification, and TypeFamilies
{-# OPTIONS_GHC -Wincomplete-patterns #-}
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE TypeFamilies #-}
newtype LEq a b = LEq { getLEq :: forall f. f a -> f b }
data Void
data Z
data S n
data List a n
= Nil (LEq Z n)
| forall m. Cons a (List a m) (LEq (S m) n)
type family F n where
F Z = ()
F (S m) = Void
newtype G n = G { getG :: F n }
hd :: List a (S n) -> a
hd (Nil e) = case getG (getLEq e (G ())) of { }
hd (Cons x xs e) = x
{-# OPTIONS_GHC -Wincomplete-patterns #-}
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE TypeFamilies #-}
data Z
data S n
type family CaseN a b n where
CaseN a b Z = a
CaseN a b (S n) = b n
data Nil = Nil
data Cons a b n = Cons a (b n)
data List a n = List (CaseN Nil (Cons a (List a)) n)
hd :: List a (S n) -> a
hd (List (Cons x xs)) = x
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment