Created
August 30, 2020 16:39
-
-
Save htsign/caf772bf0dd0281e023f28cb52c3d29a to your computer and use it in GitHub Desktop.
OCamlではモナドを一般化できない…?
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
module Monad = struct | |
module type MonadType = sig | |
type 'a t | |
val map : ('a -> 'b) -> 'a t -> 'b t | |
val return : 'a -> 'a t | |
val apply : ('a -> 'b) t -> 'a t -> 'b t | |
val flatmap : ('a -> 'b t) -> 'a t -> 'b t | |
end | |
module type MonadType2 = sig | |
include MonadType | |
type ('a, 'b) t | |
val map : ('a -> 'b) -> ('a, 'c) t -> ('b, 'c) t | |
val return : 'a -> ('a, 'b) t | |
val apply : ('a -> 'b, 'c) t -> ('a, 'c) t -> ('b, 'c) t | |
val flatmap : ('a -> ('b, 'c) t) -> ('a, 'c) t -> ('b, 'c) t | |
end | |
module Make (M : MonadType) = struct | |
type 'a t = 'a M.t | |
let map = M.map | |
let return = M.return | |
let apply = M.apply | |
let flatmap = M.flatmap | |
end | |
module Make2 (M : MonadType2) = struct | |
type ('a, 'b) t = ('a, 'b) M.t | |
let map = M.map | |
let return = M.return | |
let apply = M.apply | |
let flatmap = M.flatmap | |
end | |
end | |
(* Compile OK *) | |
module List' = Monad.Make (struct | |
type 'a t = 'a list | |
let map = List.map | |
let return x = [x] | |
let apply fs xs = | |
let rec aux acc fs' xs' = | |
match fs', xs' with | |
| [], _ -> acc | |
| f' :: fs' as fs'', x' :: xs' -> aux (f' x' :: acc) fs'' xs' | |
| _ :: fs', [] -> aux acc fs' xs | |
in | |
aux [] fs xs |> List.rev | |
let flatmap f xs = | |
let rec aux f acc = function | |
| [] -> acc | |
| x :: xs -> aux f (f x acc) xs | |
in | |
aux (fun x xs -> aux List.cons xs (f x)) [] xs |> List.rev | |
end) | |
(* Compile OK *) | |
module Option' = Monad.Make (struct | |
type 'a t = 'a option | |
let map = Option.map | |
let return x = Some x | |
let apply f x = | |
match f, x with | |
| Some f, Some x -> return @@ f x | |
| _ -> None | |
let flatmap f = function None -> None | Some x -> f x | |
end) | |
(* How do I write this without `MonadType2` and `Monad.Make2`? *) | |
module Result' = Monad.Make2 (struct | |
type ('a, 'e) t = ('a, 'e) result | |
let map = Result.map | |
let return x = Ok x | |
let apply f x = | |
match f, x with | |
| Ok f, Ok x -> return @@ f x | |
| Ok _, Error e -> Error e | |
| Error e, Ok _ -> Error e | |
| Error e, _ -> Error e | |
let flatmap f = function | |
| Error e -> Error e | |
| Ok x -> f x | |
end) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment