2023-11-15 12:24:54 +03:00
|
|
|
|
module Traits2;
|
|
|
|
|
|
|
|
|
|
trait
|
|
|
|
|
type Functor (f : Type -> Type) :=
|
|
|
|
|
mkFunctor {fmap : {A B : Type} -> (A -> B) -> f A -> f B};
|
|
|
|
|
|
|
|
|
|
trait
|
|
|
|
|
type Monad (f : Type -> Type) :=
|
|
|
|
|
mkMonad {
|
|
|
|
|
functor : Functor f;
|
|
|
|
|
return : {A : Type} -> A -> f A;
|
|
|
|
|
bind : {A B : Type} -> f A -> (A -> f B) -> f B
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
trait
|
|
|
|
|
type Semigroup (a : Type) :=
|
|
|
|
|
mkSemigroup {sconcat : a -> a -> a};
|
|
|
|
|
|
|
|
|
|
import Stdlib.Data.Fixity open;
|
|
|
|
|
|
|
|
|
|
syntax operator <> additive;
|
|
|
|
|
<> : {A : Type} -> {{Semigroup A}} -> A -> A -> A :=
|
|
|
|
|
Semigroup.sconcat;
|
|
|
|
|
|
|
|
|
|
trait
|
|
|
|
|
type Monoid (a : Type) :=
|
|
|
|
|
mkMonoid {
|
|
|
|
|
semigroup : Semigroup a;
|
|
|
|
|
mempty : a
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type Maybe (a : Type) :=
|
|
|
|
|
| nothing
|
|
|
|
|
| just a;
|
|
|
|
|
|
|
|
|
|
Maybe-fmap {A B : Type} (f : A -> B) : Maybe A -> Maybe B
|
|
|
|
|
| nothing := nothing
|
|
|
|
|
| (just x) := just (f x);
|
|
|
|
|
|
|
|
|
|
instance
|
|
|
|
|
Maybe-Functor : Functor Maybe := mkFunctor Maybe-fmap;
|
|
|
|
|
|
|
|
|
|
syntax fixity bind := binary {assoc := left};
|
|
|
|
|
|
|
|
|
|
syntax operator >>= bind;
|
|
|
|
|
>>=
|
|
|
|
|
: {M : Type -> Type}
|
|
|
|
|
-> {{Monad M}}
|
|
|
|
|
-> {A B : Type}
|
|
|
|
|
-> M A
|
|
|
|
|
-> (A -> M B)
|
|
|
|
|
-> M B := Monad.bind;
|
|
|
|
|
|
2023-12-07 13:26:48 +03:00
|
|
|
|
Maybe-bind
|
|
|
|
|
{A B : Type} : Maybe A -> (A -> Maybe B) -> Maybe B
|
2023-11-15 12:24:54 +03:00
|
|
|
|
| nothing _ := nothing
|
|
|
|
|
| (just a) f := f a;
|
|
|
|
|
|
|
|
|
|
instance
|
|
|
|
|
Maybe-Monad : Monad Maybe :=
|
|
|
|
|
mkMonad@{
|
|
|
|
|
return := just;
|
|
|
|
|
bind := Maybe-bind;
|
|
|
|
|
functor := Maybe-Functor
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
import Stdlib.Data.Bool open;
|
|
|
|
|
import Stdlib.Function open;
|
2024-06-26 11:23:35 +03:00
|
|
|
|
import Stdlib.Data.Pair open;
|
2023-11-15 12:24:54 +03:00
|
|
|
|
|
2024-06-26 11:23:35 +03:00
|
|
|
|
×-fmap {A B C : Type} (f : B -> C) : Pair A B -> Pair A C
|
2023-11-15 12:24:54 +03:00
|
|
|
|
| (a, b) := a, f b;
|
|
|
|
|
|
2024-06-26 11:23:35 +03:00
|
|
|
|
×-Functor : {A : Type} -> Functor (Pair A) :=
|
2023-11-15 12:24:54 +03:00
|
|
|
|
mkFunctor ×-fmap;
|
|
|
|
|
|
2023-12-07 13:26:48 +03:00
|
|
|
|
×-bind
|
|
|
|
|
{A : Type}
|
|
|
|
|
{{Semigroup A}}
|
|
|
|
|
{B C : Type}
|
2024-06-26 11:23:35 +03:00
|
|
|
|
: Pair A B -> (B -> Pair A C) -> Pair A C
|
2024-05-22 20:14:03 +03:00
|
|
|
|
| (a, b) f := case f b of a', b' := a <> a', b';
|
2023-11-15 12:24:54 +03:00
|
|
|
|
|
|
|
|
|
instance
|
2023-12-07 13:26:48 +03:00
|
|
|
|
×-Monad
|
2024-06-26 11:23:35 +03:00
|
|
|
|
{A : Type}
|
|
|
|
|
{{Semigroup A}}
|
|
|
|
|
{{Monoid A}}
|
|
|
|
|
: Monad (Pair A) :=
|
2023-11-15 12:24:54 +03:00
|
|
|
|
mkMonad@{
|
|
|
|
|
bind := ×-bind;
|
|
|
|
|
return := λ {b := Monoid.mempty, b};
|
|
|
|
|
functor := ×-Functor
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type Reader (r a : Type) := mkReader {runReader : r -> a};
|
|
|
|
|
|
2023-12-07 13:26:48 +03:00
|
|
|
|
Reader-fmap
|
|
|
|
|
{R A B : Type} (f : A -> B) : Reader R A -> Reader R B
|
2024-06-26 11:23:35 +03:00
|
|
|
|
| (mkReader ra) := mkReader (f << ra);
|
2023-11-15 12:24:54 +03:00
|
|
|
|
|
|
|
|
|
Reader-Functor-NoNamed {R : Type} : Functor (Reader R) :=
|
|
|
|
|
mkFunctor Reader-fmap;
|
|
|
|
|
|
|
|
|
|
instance
|
|
|
|
|
Reader-Functor {R : Type} : Functor (Reader R) :=
|
|
|
|
|
mkFunctor@{
|
|
|
|
|
fmap {A B : Type} (f : A -> B) : Reader R A -> Reader R B
|
2024-06-26 11:23:35 +03:00
|
|
|
|
| (mkReader ra) := mkReader (f << ra)
|
2023-11-15 12:24:54 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
instance
|
|
|
|
|
Reader-Monad {R : Type} : Monad (Reader R) :=
|
|
|
|
|
mkMonad@{
|
|
|
|
|
functor := Reader-Functor;
|
|
|
|
|
return {A : Type} (a : A) : Reader R A :=
|
|
|
|
|
mkReader (const a);
|
2023-12-07 13:26:48 +03:00
|
|
|
|
bind
|
|
|
|
|
{A B : Type}
|
2023-11-15 12:24:54 +03:00
|
|
|
|
: Reader R A -> (A -> Reader R B) -> Reader R B
|
|
|
|
|
| (mkReader ra) arb :=
|
|
|
|
|
let
|
|
|
|
|
open Reader;
|
|
|
|
|
in mkReader λ {r := runReader (arb (ra r)) r}
|
|
|
|
|
};
|