Skip to content

Instantly share code, notes, and snippets.

@JadenGeller
Last active November 28, 2017 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JadenGeller/d175c7684e872566bd509ee51449250d to your computer and use it in GitHub Desktop.
Save JadenGeller/d175c7684e872566bd509ee51449250d to your computer and use it in GitHub Desktop.
Dependent sums subsume algebraic data types in presence of enums
%hide Nat
%hide Nat.S
%hide Nat.Z
function : List Type -> Type -> Type
function [] b = b
function (a :: as) b = a -> function as b
infixr 10 *->
(*->) : List Type -> Type -> Type
(*->) = function
tuple : List Type -> Type
tuple [] = ()
tuple (a :: as) = (a, tuple as)
map : (a -> b) -> (args *-> a) -> (args *-> b)
map f {args=[]} z = f z
map f {args=(a :: as)} g = \x => map f (g x)
tupleConstructor : (args : List Type) -> args *-> (tuple args)
tupleConstructor [] = ()
tupleConstructor (a :: as) = \x => map (\xs => (x, xs)) (tupleConstructor as)
tupleEliminator : tuple args -> (args *-> a) -> a
tupleEliminator {args=[]} () z = z
tupleEliminator {args=(a :: as)} (x, xs) g = tupleEliminator xs (g x)
--
%auto_implicits off
record AlgebraicData (Tag : Type) (Payload : Tag -> List Type) where
constructor MkAlgebraicDataRaw
tag : Tag
payload : tuple (Payload tag)
%auto_implicits on
MkAlgebraicData : {Tag : _, Payload : _} -> (tag : Tag) -> Payload tag *-> AlgebraicData Tag Payload
MkAlgebraicData tag {Payload} = map (MkAlgebraicDataRaw tag) (tupleConstructor (Payload tag))
prefix 1 #
(#) : {Tag : _, Payload : _} -> (tag : Tag) -> Payload tag *-> AlgebraicData Tag Payload
(#) = MkAlgebraicData
elimAlgebraicData : {Tag : _, Payload : _} -> ((tag : Tag) -> Payload tag *-> a) -> AlgebraicData Tag Payload -> a
elimAlgebraicData eliminator (MkAlgebraicDataRaw tag payload) = tupleEliminator payload (eliminator tag)
--
mutual
data NatTag = Z | S
NatPayload : NatTag -> List Type
NatPayload Z = []
NatPayload S = [Nat]
Nat : Type
Nat = AlgebraicData NatTag NatPayload
MkNat : (tag : NatTag) -> NatPayload tag *-> Nat
MkNat = MkAlgebraicData
elimNat : ((tag : NatTag) -> NatPayload tag *-> a) -> Nat -> a
elimNat = elimAlgebraicData
{- commented out due to Idris type system bug
three : Nat
three = #S (#S (#S (#Z)))
double : Nat -> Nat
double = elimNat double'
where double' : (tag : NatTag) -> NatPayload tag *-> (AlgebraicData NatTag NatPayload)
double' Z = #Z
double' S x = #S (#S (double x))
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment