只是为了练习 monad 的概念,我正在尝试编写一个带有
return
和 >>=
函数的 OCaml 程序,这对于 int option
类型是有意义的。特别是,在我看来,无论这些是如何定义的,它都应该允许一个人写
let x = (return 1) >>= (return 2) >>= oplus;;
和
x
应该存储Some 3
。我认为 return
的定义是显而易见的。我认为 >>=
的合理定义应该是
let (>>=) (wrapped : int option) (handler : int -> 'a option) : 'a option =
match wrapped with
| None -> None
| Some i -> handler i
但是我不太清楚
oplus
应该如何定义,因为我认为我们应该对函数进行(return 2) >>= oplus
评估
fun i -> Some(i+2)
但是这些参数的绑定结果是错误的。
很明显我误会了什么——我猜我认为
Some 11 >>= Some 2 >>= oplus
应该评估为 Some 13
是错误的。但我认为这是一种想法或绑定点,就像数据管道一样,将数据馈送到函数中,解包、计算,然后在最后再次包装它。
假设
return
实现为:
let return (x: int) = Some x
那么
(return 1) >>= (return 2)
就相当于写Some 1 >>= Some 2
.
这行不通,因为
>>=
期望右侧是一个函数。
utop # (return 1) >>= (return 2);;
Error: This expression has type int option
but an expression was expected of type int -> 'a option
如果我们尝试以下操作,由于
>>=
运算符的关联性,它会失败。
return 11 >>= return 2 >>= oplus
这被解析为:
(return 11 >>= return 2) >>= oplus
如果我们用以下方式消除该订单的歧义:
return 11 >>= (return 2 >>= oplus)
然后右边的操作数是一个
int option
,同样,类型不成立。