module 1Lab.Type.Pi.Currying whereCurrying 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) β AThe 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 cFinally, 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) β AHowever, 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! #-}