module 1Lab.Type.Pi.Currying where
Currying and uncurrying automationπ
This module contains proof automation for passing between curried and uncurried Ξ types.
Curryingπ
The core of our currying automation is the following typeclass, which decomposes a type into a Ξ type.
record Curried {β} (A : Type β) (βd βf : Level) : Type (β β lsuc βd β lsuc βf) where no-eta-equality field Dom : Type βd Cod : Dom β Type βf eqv : ((d : Dom) β Cod d) β A
The only interesting instances of Curried
check to see
if
is an iterated Ξ type, and shuffle over elements of the codomain into a
Ξ£ in the domain.
instance Curried-Ξ : β {β β' β'' βd βf} {A : Type β} {B : A β Type β'} {C : (a : A) β B a β Type β''} β β¦ _ : β {a} β Curried ((b : B a) β C a b) βd βf β¦ β Curried ((a : A) (b : B a) β C a b) (βd β β) βf Curried-Ξ {A = A} β¦ c β¦ .Curried.Dom = Ξ£[ a β A ] (Curried.Dom (c {a})) Curried-Ξ {A = A} β¦ c β¦ .Curried.Cod (a , d) = Curried.Cod c d Curried-Ξ {A = A} β¦ c β¦ .Curried.eqv = curryβ βe Ξ -ap-cod Ξ» a β Curried.eqv c Curried-Ξ ' : β {β β' β'' βd βf} {A : Type β} {B : A β Type β'} {C : (a : A) β B a β Type β''} β β¦ _ : β {a} β Curried ((b : B a) β C a b) βd βf β¦ β Curried ({a : A} (b : B a) β C a b) (βd β β) βf Curried-Ξ ' {A = A} β¦ c β¦ .Curried.Dom = Ξ£[ a β A ] (Curried.Dom (c {a})) Curried-Ξ ' {A = A} β¦ c β¦ .Curried.Cod (a , d) = Curried.Cod c d Curried-Ξ ' {A = A} β¦ c β¦ .Curried.eqv = curryβ βe Ξ -implβ βe Ξ '-ap-cod Ξ» a β Curried.eqv c
Finally, we have an INCOHERENT
base case that will match
only when we have run out of iterated Ξ types.
Curried-default : β {β β'} {A : Type β} {B : A β Type β'} β Curried ((a : A) β B a) β β' Curried-default {A = A} {B = B} .Curried.Dom = A Curried-default {A = A} {B = B} .Curried.Cod = B Curried-default {A = A} {B = B} .Curried.eqv = idβ {-# INCOHERENT Curried-default #-}
Now that weβve got our instances in place, we can use instance arguments to compute the fully curried version of a type.
Curry : β {β βd βf} β (A : Type β) β β¦ C : Curried A βd βf β¦ β Type (βd β βf) Curry A β¦ C β¦ = (x : Curried.Dom C) β Curried.Cod C x {-# NOINLINE Curry #-}
We also expose the equivlance between the original type and itβs curried form.
curry! : β {β βd βf} β {A : Type β} β β¦ C : Curried A βd βf β¦ β A β Curry A curry! β¦ C β¦ = Curried.eqv C eβ»ΒΉ {-# NOINLINE curry! #-}
Uncurryingπ
The uncurrying typeclass is identical to the currying typeclass in all but name.
record Uncurried {β} (A : Type β) (βd βf : Level) : Type (β β lsuc βd β lsuc βf) where no-eta-equality field Dom : Type βd Cod : Dom β Type βf eqv : ((d : Dom) β Cod d) β A
However, the instances for Uncurried
go in the opposite
direction.
instance Uncurried-Ξ : β {β β' β'' βd βf} {A : Type β} {B : A β Type β'} {C : Ξ£ A B β Type β''} β β¦ _ : β {a} β Uncurried ((b : B a) β C (a , b)) βd βf β¦ β Uncurried ((ab : Ξ£ A B) β C ab) β (βd β βf) Uncurried-Ξ {A = A} β¦ c β¦ .Uncurried.Dom = A Uncurried-Ξ {A = A} β¦ c β¦ .Uncurried.Cod a = (d : Uncurried.Dom (c {a})) β Uncurried.Cod (c {a}) d Uncurried-Ξ {A = A} β¦ c β¦ .Uncurried.eqv = Ξ -ap-cod (Ξ» a β Uncurried.eqv c) βe curryβ eβ»ΒΉ Uncurried-default : β {β β'} {A : Type β} {B : A β Type β'} β Uncurried ((a : A) β B a) β β' Uncurried-default {A = A} {B = B} .Uncurried.Dom = A Uncurried-default {A = A} {B = B} .Uncurried.Cod = B Uncurried-default {A = A} {B = B} .Uncurried.eqv = idβ
We expose a similar API for uncurrying.
Uncurry : β {β βd βf} β (A : Type β) β β¦ C : Uncurried A βd βf β¦ β Type (βd β βf) Uncurry A β¦ C β¦ = (x : Uncurried.Dom C) β Uncurried.Cod C x {-# NOINLINE Uncurry #-} uncurry! : β {β βd βf} β {A : Type β} β β¦ C : Uncurried A βd βf β¦ β A β Uncurry A uncurry! β¦ C β¦ = Uncurried.eqv C eβ»ΒΉ {-# NOINLINE uncurry! #-}