Last active
August 29, 2015 14:11
-
-
Save jobjo/b03444db396a2f3f14ad to your computer and use it in GitHub Desktop.
What if F# supported higher-kinded polymorphism?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Functor interface. | |
| type Functor<'F> = { map : ('T -> 'U) -> 'F<'T> -> 'F<'U> } | |
| // Monad interface. | |
| type Monad<'M> = { | |
| return : 'T -> 'M<'T> | |
| join : 'M<'M<'T>> -> 'M<'T> | |
| } | |
| // Monad "library" (operations over monads). | |
| // Assuming: | |
| // - higher-kinded polymorphism | |
| // - polymorphic fields (existentially quantified) | |
| type MonadUtils<'M> = { | |
| bind : 'M<'T> -> ('T -> 'M<'S>) -> 'M<'S> | |
| sequence : Seq<'M<'T>> -> 'M<List<'T>> | |
| } | |
| // Function for building a Monad Utils "library". | |
| let buildMonadUtils (M: Monad<'M>) (F: Functor<'F>) = | |
| let bind m g = M.join (F.map g m) | |
| let rec sequence = function | |
| | [] -> M.return | |
| | x :: xs -> bind x (fun y -> bind (sequence xs) (fun ys -> y :: ys)) | |
| { | |
| bind = bind | |
| sequence = List.ofSeq >> sequence | |
| } | |
| // Functor instance for option types. | |
| let optionFunctor = {map = Option.map} | |
| // Monad instance for option types. | |
| let optionMonad = | |
| let join = function | |
| | Some x -> x | |
| | _ -> None | |
| {return = Some; join = join} | |
| // Builds the monad library for option types. | |
| let OM = buildMonadUtils optionFunctor optionMonad | |
| OM.sequence [Some 42 Some 11] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment