参考:さらにSRTPを駆使すると……
module Monad =
type CMonad() =
static member inline bind(f: ^a -> ^b list, m: ^a list) = List.collect f m
static member inline bind(f: ^a -> ^b option, m: ^a option) = Option.bind f m
static member inline bind_resolve< ^m, ^a, ^b, ^c
when ^m :> CMonad and (^m or ^c): (static member bind: (^a -> ^b) * ^c -> ^b)>
(f: ^a -> ^b, m: ^c) =
((^m or ^c): (static member bind: (^a -> ^b) * ^c -> ^b) (f, m))
let inline bind< ^a, ^b, ^c
when (CMonad or ^c): (static member bind: (^a -> ^b) * ^c -> ^b)>
(f: ^a -> ^b) (m: ^c) : ^b =
CMonad.bind_resolve<CMonad, _, _, _> (f, m)
let m1 = Some 1 |> Monad.bind (fun x -> Some (string x))