type'aMaybe=Justof'a|Nothing(* Functor *)type'aMaybewithstaticmemberfmap():('a->'b)->'aMaybe->'bMaybe=funf->function|Justx->fx|>Just|Nothing->Nothing(* Applicative *)type'aMaybewithstaticmemberliftA():('a->'b)Maybe->'aMaybe->'bMaybe=funfm->funm->matchfm,mwith|Justf,Justx->fx|>Just|______________->Nothing(* Monad *)type'aMaybewithstaticmemberliftM():'aMaybe->('a->'bMaybe)->'bMaybe=funm->funf->matchmwith|Nothing->Nothing|Justx->fx(* Maybe with functions, the amount of parenthesis is to damn high *)fmap((+)1)(Just42);;liftA(Just((+)1))(Just42);;liftM(Just42)(funx->x+1|>Just);;(* Maybe with operators, fewer parenthesis *)((+)1)<@>Just42;;Just((+)1)<*>Just42;;Just42>>=funx->x+1|>Just;;
Maybe (Option) with fmap, liftA and liftM Code output:
Vect (list) with fmap, liftA and liftM Code Snippet
(* A list in F# is just a type abbreviation of a FSharpList *)typedefof<List<_>>=typedefof<_list>(* Functor *)type'aListwithstaticmemberfmap():('a->'b)->'alist->'blist=List.map(* This works *)List.fmap()((+)1)[0..10](* but this doesn't *)//fmap((+)1)<@>[42](* error FS0001: The type ''a list' does not support the operator 'fmap' *)(* Therefore, lets create our own type wrapping native lists in a Vector *)type'aVect=Vectof'alist(* Functor *)type'aVectwithstaticmemberfmap():('a->'b)->'aVect->'bVect=funf->fun(Vectxs)->List.mapfxs|>Vect(* Applicative *)type'aVectwithstaticmemberliftA():('a->'b)Vect->'aVect->'bVect=fun(Vectfs)->fun(Vectxs)->fs|>List.map(funf->xs|>List.mapf)|>List.concat|>Vect(* Monad *)type'aVectwithstaticmemberliftM():'aVect->('alist->'bVect)->'bVect=fun(Vectxs)->funf->fxs(* Vect with operators, fewer parenthesis *)((+)1)<@>Vect[0..5];;Vect[id;((+)1)]<*>Vect[0..5];;Vect[0..5]>>=funxs->xs|>List.map((+)1)|>Vect;;
Vect (list) with fmap, liftA and liftM Code output:
Result (Choice) with fmap, liftA and liftM Code Snippet