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
: Type βd
Dom : Dom β Type βf
Cod : ((d : Dom) β Cod d) β A eqv
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
{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-Ξ
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
{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 Curried-Ξ '
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) β β'
{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β
Curried-default {-# 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.
: β {β βd βf} β (A : Type β) β β¦ C : Curried A βd βf β¦ β Type (βd β βf)
Curry = (x : Curried.Dom C) β Curried.Cod C x
Curry A β¦ C β¦ {-# 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
= Curried.eqv C eβ»ΒΉ
curry! β¦ C β¦ {-# 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
: Type βd
Dom : Dom β Type βf
Cod : ((d : Dom) β Cod d) β A eqv
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)
{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-Ξ
Uncurried-default: β {β β'} {A : Type β} {B : A β Type β'}
β Uncurried ((a : A) β B a) β β'
{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β Uncurried-default
We expose a similar API for uncurrying.
: β {β βd βf} β (A : Type β) β β¦ C : Uncurried A βd βf β¦ β Type (βd β βf)
Uncurry = (x : Uncurried.Dom C) β Uncurried.Cod C x
Uncurry A β¦ C β¦ {-# NOINLINE Uncurry #-}
uncurry!: β {β βd βf}
β {A : Type β}
β β¦ C : Uncurried A βd βf β¦
β A β Uncurry A
= Uncurried.eqv C eβ»ΒΉ
uncurry! β¦ C β¦ {-# NOINLINE uncurry! #-}