MathClasses.interfaces.functors
Require Import
abstract_algebra.
Require Import
theory.setoids.
Section functor_class.
Context `{Category C} `{Category D} (M: C → D).
Class Fmap: Type := fmap: ∀ {v w: C}, (v ⟶ w) → (M v ⟶ M w).
Class Functor `(Fmap): Prop :=
{ functor_from: Category C
; functor_to: Category D
; functor_morphism:> ∀ a b: C, Setoid_Morphism (@fmap _ a b)
; preserves_id: `(fmap (cat_id: a ⟶ a) = cat_id)
; preserves_comp `(f: y ⟶ z) `(g: x ⟶ y): fmap (f ◎ g) = fmap f ◎ fmap g }.
End functor_class.
Typeclasses Transparent Fmap.
Section id_functor.
Context `{Category C}.
Global Instance: Fmap id := λ _ _, id.
Global Instance id_functor: Functor (id: C → C) _.
Proof.
constructor; try reflexivity; try apply _. intros.
change (Setoid_Morphism (id: (a ⟶ b) → (a ⟶ b))).
apply _.
Qed.
End id_functor.
Section compose_functors.
Context
A B C
`{!Arrows A} `{!Arrows B} `{!Arrows C}
`{!CatId A} `{!CatId B} `{!CatId C}
`{!CatComp A} `{!CatComp B} `{!CatComp C}
`{∀ x y: A, Equiv (x ⟶ y)}
`{∀ x y: B, Equiv (x ⟶ y)}
`{∀ x y: C, Equiv (x ⟶ y)}
`{!Functor (f: B → C) f'} `{!Functor (g: A → B) g'}.
Global Instance comp_Fmap: Fmap (f ∘ g) := λ _ _, fmap f ∘ fmap g.
Global Instance compose_functors: Functor (f ∘ g) _.
Proof with intuition; try apply _.
pose proof (functor_from g).
pose proof (functor_to g).
pose proof (functor_to f).
constructor; intros; try apply _.
apply (@setoids.compose_setoid_morphism _ _ _ _ _ _)...
apply (@functor_morphism _ _ _ _ _ _ _ _ _ _ f _)...
change (fmap f (fmap g (cat_id: a ⟶ a)) = cat_id).
repeat try rewrite preserves_id...
change (fmap f (fmap g (f0 ◎ g0)) = fmap f (fmap g f0) ◎ fmap f (fmap g g0)).
repeat try rewrite preserves_comp...
Qed.
End compose_functors.
abstract_algebra.
Require Import
theory.setoids.
Section functor_class.
Context `{Category C} `{Category D} (M: C → D).
Class Fmap: Type := fmap: ∀ {v w: C}, (v ⟶ w) → (M v ⟶ M w).
Class Functor `(Fmap): Prop :=
{ functor_from: Category C
; functor_to: Category D
; functor_morphism:> ∀ a b: C, Setoid_Morphism (@fmap _ a b)
; preserves_id: `(fmap (cat_id: a ⟶ a) = cat_id)
; preserves_comp `(f: y ⟶ z) `(g: x ⟶ y): fmap (f ◎ g) = fmap f ◎ fmap g }.
End functor_class.
Typeclasses Transparent Fmap.
Section id_functor.
Context `{Category C}.
Global Instance: Fmap id := λ _ _, id.
Global Instance id_functor: Functor (id: C → C) _.
Proof.
constructor; try reflexivity; try apply _. intros.
change (Setoid_Morphism (id: (a ⟶ b) → (a ⟶ b))).
apply _.
Qed.
End id_functor.
Section compose_functors.
Context
A B C
`{!Arrows A} `{!Arrows B} `{!Arrows C}
`{!CatId A} `{!CatId B} `{!CatId C}
`{!CatComp A} `{!CatComp B} `{!CatComp C}
`{∀ x y: A, Equiv (x ⟶ y)}
`{∀ x y: B, Equiv (x ⟶ y)}
`{∀ x y: C, Equiv (x ⟶ y)}
`{!Functor (f: B → C) f'} `{!Functor (g: A → B) g'}.
Global Instance comp_Fmap: Fmap (f ∘ g) := λ _ _, fmap f ∘ fmap g.
Global Instance compose_functors: Functor (f ∘ g) _.
Proof with intuition; try apply _.
pose proof (functor_from g).
pose proof (functor_to g).
pose proof (functor_to f).
constructor; intros; try apply _.
apply (@setoids.compose_setoid_morphism _ _ _ _ _ _)...
apply (@functor_morphism _ _ _ _ _ _ _ _ _ _ f _)...
change (fmap f (fmap g (cat_id: a ⟶ a)) = cat_id).
repeat try rewrite preserves_id...
change (fmap f (fmap g (f0 ◎ g0)) = fmap f (fmap g f0) ◎ fmap f (fmap g g0)).
repeat try rewrite preserves_comp...
Qed.
End compose_functors.
The Functor class is nice and abstract and theory-friendly, but not as convenient
to use for regular programming as Haskell's Functor class. The reason for this is that
our Functor is parameterized on two Categories, which by necessity bundle setoid-
ness and setoid-morphism-ness into objects and arrows, respectively.
The Haskell Functor class, by contrast, is essentially specialized for endofunctors on
the category of Haskell types and functions between them. The latter corresponds to our
setoid.Object category.
To recover convenience, we introduce a second functor type class tailored specifically to
functors of this kind. The specialization allows us to forgo bundling, and lets us recover
the down-to-earth Type→Type type for the type constructor, and the (a→b)→(F a→F b)
type for the function map, with all setoid/morphism proofs hidden in the structure class
in Prop.
To justify this definition, in theory/functors we show that instances of this new functor
class do indeed give rise to instances of the original nice abstract Functor class.
Class SFmap (M : Type → Type) := sfmap: ∀ `(A → B), (M A → M B).
Class SFunctor (M : Type → Type)
`{∀ `{Equiv A}, Equiv (M A)} `{SFmap M} : Prop :=
{ sfunctor_setoid `{Setoid A} :> Setoid (M A)
; sfmap_proper `{Setoid A} `{Setoid B} :>
Proper (((=) ==> (=)) ==> ((=) ==> (=))) (@sfmap M _ A B)
; sfmap_id `{Setoid A} : sfmap id = id
; sfmap_comp `{Equiv A} `{Equiv B} `{Equiv C} `{!Setoid_Morphism (f : B → C)} `{!Setoid_Morphism (g : A → B)} :
sfmap (f ∘ g) = sfmap f ∘ sfmap g }.