1
1
mirror of https://github.com/anoma/juvix.git synced 2024-12-04 17:07:28 +03:00
juvix/tests/positive/Traits2.juvix

126 lines
2.6 KiB
Plaintext
Raw Normal View History

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;
Maybe-bind
{A B : Type} : Maybe A -> (A -> Maybe B) -> Maybe B
| 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;
import Stdlib.Data.Pair open;
×-fmap {A B C : Type} (f : B -> C) : Pair A B -> Pair A C
| (a, b) := a, f b;
×-Functor : {A : Type} -> Functor (Pair A) :=
mkFunctor ×-fmap;
×-bind
{A : Type}
{{Semigroup A}}
{B C : Type}
: Pair A B -> (B -> Pair A C) -> Pair A C
| (a, b) f := case f b of a', b' := a <> a', b';
instance
×-Monad
{A : Type}
{{Semigroup A}}
{{Monoid A}}
: Monad (Pair A) :=
mkMonad@{
bind := ×-bind;
return := λ {b := Monoid.mempty, b};
functor := ×-Functor
};
type Reader (r a : Type) := mkReader {runReader : r -> a};
Reader-fmap
{R A B : Type} (f : A -> B) : Reader R A -> Reader R B
| (mkReader ra) := mkReader (f << ra);
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
| (mkReader ra) := mkReader (f << ra)
};
instance
Reader-Monad {R : Type} : Monad (Reader R) :=
mkMonad@{
functor := Reader-Functor;
return {A : Type} (a : A) : Reader R A :=
mkReader (const a);
bind
{A B : Type}
: Reader R A -> (A -> Reader R B) -> Reader R B
| (mkReader ra) arb :=
let
open Reader;
in mkReader λ {r := runReader (arb (ra r)) r}
};