Skip to content

Instantly share code, notes, and snippets.

@htsign
Created August 30, 2020 16:39
Show Gist options
  • Save htsign/caf772bf0dd0281e023f28cb52c3d29a to your computer and use it in GitHub Desktop.
Save htsign/caf772bf0dd0281e023f28cb52c3d29a to your computer and use it in GitHub Desktop.
OCamlではモナドを一般化できない…?
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