The common signature of functions declarations in a module is when the last parameter has a type of the main state (Module.t). Like it is in the 'List' module. This form opens the ability to use '|>' operator like:
[1;2;3] |> List.filter ((>)2)
|> List.map ((-)1)
|> List.fold_left 0 (+)
But function 'bind' in 'Option' module doesn't follow this form. It has 'Option.t' parameter as the first
val bind : 'a option -> ('a -> 'b option) -> 'b option
But ok, I can change it. I declared function 'opt_bind' with the reverse order of parameters.
let opt_bind = Fun.flip Option.bind
But this one doesn't work. And the following code was compiled with the following error
type a = A of int
type b = B of int
let f x = Some (A x)
let g (A x) = Some (B x)
let opt_bind = Fun.flip Option.bind
let result =
(Some 42) |> opt_bind f
|> opt_bind g
|> opt_bind g ^
Error: This expression has type a -> b option but an expression was expected of > type int -> a option. Type a is not compatible with type int
The same situation with
let result =
let x = opt_bind f (Some 42) in
let x = opt_bind g x in
x
Even after I had noticed all types I still have the same problem.
let f : int -> a option = fun x -> Some (A x)
let g : a -> b option = fun (A x) -> Some (B x)
let opt_bind : ('a -> 'b option) -> 'a option -> 'b option =
Fun.flip Option.bind
let result : b option =
let x : a option = opt_bind f (Some 42) in
let x : b option = opt_bind g x in
x ;;
But
let result =
let x = Option.bind (Some 42) f in
let x = Option.bind x g in
x
works fine.
Why does 'opt_bind' have the wrong type expectation for 'g' as if 'opt_bind' isn't generic?
How to use 'bind' with '|>' notation?