1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
use crate::*; pub struct TypeCon; impl<T> TypeAppParam for Option<T> { type Param = T; } impl<T> TypeApp<TypeCon, T> for Option<T> {} impl<T> WithTypeArg<T> for TypeCon { type Type = Option<T>; } impl Functor for TypeCon { fn fmap<TIn, TOut, F>( f: F, x: &<TypeCon as WithTypeArg<TIn>>::Type, ) -> <TypeCon as WithTypeArg<TOut>>::Type where F: Fn(&TIn) -> TOut, { Option::map(x.as_ref(), f) } } impl LinearFunctor for TypeCon { fn lmap<TIn, TOut, F>( f: F, x: <TypeCon as WithTypeArg<TIn>>::Type, ) -> <TypeCon as WithTypeArg<TOut>>::Type where F: Fn(TIn) -> TOut, { Option::map(x, f) } } impl Lift for TypeCon { fn lift<T>(x: T) -> <TypeCon as WithTypeArg<T>>::Type { From::from(x) } } impl Applicative for TypeCon { fn ap<TIn, TOut, TFunc>( f: &<TypeCon as WithTypeArg<TFunc>>::Type, x: &<TypeCon as WithTypeArg<TIn>>::Type, ) -> <TypeCon as WithTypeArg<TOut>>::Type where TFunc: Fn(&TIn) -> TOut, { f.as_ref().and_then(|f_val| fmap(f_val, x)) } fn lift2<TIn1, TIn2, TOut, TFunc>( f: TFunc, x1: &<TypeCon as WithTypeArg<TIn1>>::Type, x2: &<TypeCon as WithTypeArg<TIn2>>::Type, ) -> <TypeCon as WithTypeArg<TOut>>::Type where TFunc: Fn(&TIn1, &TIn2) -> TOut, { x1.as_ref() .and_then(|x1_val| x2.as_ref().map(|x2_val| f(x1_val, x2_val))) } } impl LinearApplicative for TypeCon { fn lap<TIn, TOut, TFunc>( f: <TypeCon as WithTypeArg<TFunc>>::Type, x: <TypeCon as WithTypeArg<TIn>>::Type, ) -> <TypeCon as WithTypeArg<TOut>>::Type where TFunc: FnOnce(TIn) -> TOut, { f.and_then(|f_val| x.map(|x_val| f_val(x_val))) } fn llift2<TIn1, TIn2, TOut, TFunc>( f: TFunc, x1: <TypeCon as WithTypeArg<TIn1>>::Type, x2: <TypeCon as WithTypeArg<TIn2>>::Type, ) -> <TypeCon as WithTypeArg<TOut>>::Type where TFunc: FnOnce(TIn1, TIn2) -> TOut, { x1.and_then(|x1val| x2.map(|x2val| f(x1val, x2val))) } } impl Monad for TypeCon { fn bind<TIn, TOut, F>( x: &<TypeCon as WithTypeArg<TIn>>::Type, f: F, ) -> <TypeCon as WithTypeArg<TOut>>::Type where F: Fn(&TIn) -> <TypeCon as WithTypeArg<TOut>>::Type, { x.as_ref().and_then(f) } } impl LinearMonad for TypeCon { fn lbind<TIn, TOut, F>( x: <TypeCon as WithTypeArg<TIn>>::Type, f: F, ) -> <TypeCon as WithTypeArg<TOut>>::Type where F: FnOnce(TIn) -> <TypeCon as WithTypeArg<TOut>>::Type, { x.and_then(f) } }