我试图围绕单子以及如何在现实世界的示例中使用它们。我给自己设定的第一个“任务”是编写一个“异常单子”,当然(此时)它只不过是为了满足我的目的而扭曲的“任一单子”。
我的代码如下所示:
type MException<'a> =
| Success of 'a
| Failure of string
with
static member returnM a =
Success a
static member bind f =
fun e ->
match e with
| Success a -> f a
| Failure m -> Failure m
static member map f =
fun e ->
match e with
| Success a -> Success (f a)
| Failure m -> Failure m
// Create a little test case to test my code
let divide (n, m) =
match m with
| 0 -> Failure "Cannot divide by zero"
| _ -> Success ((float n) / (float m))
let round (f:float) =
Success ( System.Math.Round(f, 3) )
let toString (f:float) =
sprintf "%f" f
let divideRoundAndPrintNumber =
divide
>> MException<_>.bind round
>> MException<_>.map toString
// write the result
let result = divideRoundAndPrintNumber (11, 3)
match result with
| Success r -> printf "%s\n" r
| Failure m -> printf "%s\n" m
我的问题如下:divide 函数现在需要一个元组。我可以或应该做些什么来使绑定和映射函数对于具有多个参数的函数的行为正确?
编辑 30-12-2015:@Mark Seemann 的答案和评论都有助于找到问题的答案。@Mikhail 提供了解决方案的实现。柯里化是解决问题的正确方法。计算表达式不是一种解决方案,而是一种语法抽象,它确实有效,但一旦您将异步和其他模式添加到问题中,它就会变得复杂。“简单”的组合似乎是最简单和“最真实”的解决方案。