open import 1Lab.Reflection
open import 1Lab.Prelude
open import Cat.Base
open import Data.List
import Cat.Reasoning as Cat
module Cat.Functor.Solver where
module NbE {o h o' h'} {π : Precategory o h} {π : Precategory o' h'} (F : Functor π π) where
private
module π = Cat π
module π = Cat π
open Functor F
variable
A B C : π.Ob
X Y Z : π.Ob
data CExpr : π.Ob β π.Ob β Type (o β h) where
_βΆββΆ_ : CExpr B C β CExpr A B β CExpr A C
βΆidβΆ : CExpr A A
_β : π.Hom A B β CExpr A B
data DExpr : π.Ob β π.Ob β Type (o β h β o' β h') where
βΆFββΆ : CExpr A B β DExpr (Fβ A) (Fβ B)
_βΆββΆ_ : DExpr Y Z β DExpr X Y β DExpr X Z
βΆidβΆ : DExpr X X
_β : π.Hom X Y β DExpr X Y
uncexpr : CExpr A B β π.Hom A B
uncexpr (e1 βΆββΆ e2) = uncexpr e1 π.β uncexpr e2
uncexpr βΆidβΆ = π.id
uncexpr (f β) = f
undexpr : DExpr X Y β π.Hom X Y
undexpr (βΆFββΆ e) = Fβ (uncexpr e)
undexpr (e1 βΆββΆ e2) = undexpr e1 π.β undexpr e2
undexpr βΆidβΆ = π.id
undexpr (f β) = f
data CValue : π.Ob β π.Ob β Type (o β h) where
vid : CValue A A
vcomp : π.Hom B C β CValue A B β CValue A C
data Frame : π.Ob β π.Ob β Type (o β h β o' β h') where
vhom : π.Hom X Y β Frame X Y
vfmap : π.Hom A B β Frame (Fβ A) (Fβ B)
data DValue : π.Ob β π.Ob β Type (o β h β o' β h') where
vid : DValue X X
vcomp : Frame Y Z β DValue X Y β DValue X Z
uncvalue : CValue A B β π.Hom A B
uncvalue vid = π.id
uncvalue (vcomp f v) = f π.β uncvalue v
unframe : Frame X Y β π.Hom X Y
unframe (vhom f) = f
unframe (vfmap f) = Fβ f
undvalue : DValue X Y β π.Hom X Y
undvalue vid = π.id
undvalue (vcomp f v) = unframe f π.β undvalue v
do-cvcomp : CValue B C β CValue A B β CValue A C
do-cvcomp vid v2 = v2
do-cvcomp (vcomp f v1) v2 = vcomp f (do-cvcomp v1 v2)
ceval : CExpr A B β CValue A B
ceval (e1 βΆββΆ e2) = do-cvcomp (ceval e1) (ceval e2)
ceval βΆidβΆ = vid
ceval (f β) = vcomp f vid
do-dvcomp : DValue Y Z β DValue X Y β DValue X Z
do-dvcomp vid v2 = v2
do-dvcomp (vcomp f v1) v2 = vcomp f (do-dvcomp v1 v2)
do-vfmap : CValue A B β DValue (Fβ A) (Fβ B)
do-vfmap vid = vid
do-vfmap (vcomp f v) = vcomp (vfmap f) (do-vfmap v)
deval : DExpr X Y β DValue X Y
deval (βΆFββΆ e) = do-vfmap (ceval e)
deval (e1 βΆββΆ e2) = do-dvcomp (deval e1) (deval e2)
deval βΆidβΆ = vid
deval (f β) = vcomp (vhom f) vid
do-cvcomp-sound : β (v1 : CValue B C) β (v2 : CValue A B) β uncvalue (do-cvcomp v1 v2) β‘ uncvalue v1 π.β uncvalue v2
do-cvcomp-sound vid v2 = sym (π.idl (uncvalue v2))
do-cvcomp-sound (vcomp f v1) v2 = π.pushr (do-cvcomp-sound v1 v2)
ceval-sound : β (e : CExpr A B) β uncvalue (ceval e) β‘ uncexpr e
ceval-sound (e1 βΆββΆ e2) =
uncvalue (do-cvcomp (ceval e1) (ceval e2)) β‘β¨ do-cvcomp-sound (ceval e1) (ceval e2) β©
(uncvalue (ceval e1) π.β uncvalue (ceval e2)) β‘β¨ apβ π._β_ (ceval-sound e1) (ceval-sound e2) β©
uncexpr e1 π.β uncexpr e2 β
ceval-sound βΆidβΆ = refl
ceval-sound (f β) = π.idr f
do-vfmap-sound : β (v : CValue A B) β undvalue (do-vfmap v) β‘ Fβ (uncvalue v)
do-vfmap-sound vid = sym F-id
do-vfmap-sound (vcomp f v) =
Fβ f π.β undvalue (do-vfmap v) β‘β¨ ap (Fβ f π.β_) (do-vfmap-sound v) β©
Fβ f π.β Fβ (uncvalue v) β‘Λβ¨ F-β f (uncvalue v) β©
Fβ (f π.β uncvalue v) β
do-dvcomp-sound : β (v1 : DValue Y Z) β (v2 : DValue X Y) β undvalue (do-dvcomp v1 v2) β‘ undvalue v1 π.β undvalue v2
do-dvcomp-sound vid v2 = sym (π.idl (undvalue v2))
do-dvcomp-sound (vcomp f v1) v2 = π.pushr (do-dvcomp-sound v1 v2)
deval-sound : β (e : DExpr X Y) β undvalue (deval e) β‘ undexpr e
deval-sound (βΆFββΆ e) =
undvalue (do-vfmap (ceval e)) β‘β¨ do-vfmap-sound (ceval e) β©
Fβ (uncvalue (ceval e)) β‘β¨ ap Fβ (ceval-sound e ) β©
Fβ (uncexpr e) β
deval-sound (e1 βΆββΆ e2) =
undvalue (do-dvcomp (deval e1) (deval e2)) β‘β¨ do-dvcomp-sound (deval e1) (deval e2) β©
undvalue (deval e1) π.β undvalue (deval e2) β‘β¨ apβ π._β_ (deval-sound e1) (deval-sound e2) β©
undexpr e1 π.β undexpr e2 β
deval-sound βΆidβΆ = refl
deval-sound (f β) = π.idr f
abstract
solve : (e1 e2 : DExpr X Y) β undvalue (deval e1) β‘ undvalue (deval e2) β undexpr e1 β‘ undexpr e2
solve e1 e2 p = sym (deval-sound e1) Β·Β· p Β·Β· (deval-sound e2)
module Reflection where
pattern category-args xs = _ hmβ· _ hmβ· _ vβ· xs
pattern functor-args functor xs =
_ hmβ· _ hmβ· _ hmβ· _ hmβ· _ hmβ· _ hmβ· functor vβ· xs
pattern βidβ =
def (quote Precategory.id) (category-args (_ hβ· []))
pattern βββ f g =
def (quote Precategory._β_) (category-args (_ hβ· _ hβ· _ hβ· f vβ· g vβ· []))
pattern βFββ functor f =
def (quote Functor.Fβ) (functor-args functor (_ hβ· _ hβ· f vβ· []))
mk-functor-args : Term β List (Arg Term) β List (Arg Term)
mk-functor-args functor args =
unknown hβ· unknown hβ· unknown hβ· unknown hβ· unknown hβ· unknown hβ· functor vβ· args
βsolveβ : Term β Term β Term β Term
βsolveβ functor lhs rhs =
def (quote NbE.solve) (mk-functor-args functor $ infer-hidden 2 $ lhs vβ· rhs vβ· def (quote refl) [] vβ· [])
build-cexpr : Term β Term
build-cexpr βidβ = con (quote NbE.CExpr.βΆidβΆ) []
build-cexpr (βββ f g) = con (quote NbE.CExpr._βΆββΆ_) (build-cexpr f vβ· build-cexpr g vβ· [])
build-cexpr f = con (quote NbE.CExpr._β) (f vβ· [])
build-dexpr : Term β Term β TC Term
build-dexpr functor βidβ =
pure $ con (quote NbE.DExpr.βΆidβΆ) []
build-dexpr functor (βββ f g) = do
f β build-dexpr functor f
g β build-dexpr functor g
pure $ con (quote NbE.DExpr._βΆββΆ_) (f vβ· g vβ· [])
build-dexpr functor (βFββ functor' f) = do
unify functor functor'
pure $ con (quote NbE.DExpr.βΆFββΆ) (build-cexpr f vβ· [])
build-dexpr functor f =
pure $ con (quote NbE.DExpr._β) (f vβ· [])
dont-reduce : List Name
dont-reduce = quote Precategory.id β· quote Precategory._β_ β· quote Functor.Fβ β· []
solve-macro : β {o h o' h'} {π : Precategory o h} {π : Precategory o' h'} β Functor π π β Term β TC β€
solve-macro functor hole =
withNormalisation false $
withReduceDefs (false , dont-reduce) $ do
functor-tm β quoteTC functor
goal β infer-type hole >>= reduce
just (lhs , rhs) β get-boundary goal
where nothing β typeError $ strErr "Can't determine boundary: " β·
termErr goal β· []
elhs β build-dexpr functor-tm lhs
erhs β build-dexpr functor-tm rhs
noConstraints $ unify hole (βsolveβ functor-tm elhs erhs)
macro
functor! : β {o h o' h'} {π : Precategory o h} {π : Precategory o' h'} β Functor π π β Term β TC β€
functor! functor = Reflection.solve-macro functor
private module Test {o h o' h'} {π : Precategory o h} {π : Precategory o' h'} (F : Functor π π) where
module π = Cat π
module π = Cat π
open Functor F
variable
A B : π.Ob
X Y : π.Ob
a b c : π.Hom A B
x y z : π.Hom X Y
test : (x π.β Fβ (π.id π.β π.id)) π.β Fβ a π.β Fβ (π.id π.β b) β‘ π.id π.β x π.β Fβ (a π.β b)
test = functor! F