我喜欢计算表达式,但我会犯一些简单的错误,比如忘记 return 关键字或 ! 关于 let! 然后返回!,或者我只是忘记写do!。状态单子经常发生这种情况,我倾向于忘记状态,只关注我定义的单子运算符。
我有时会确保我的单子运算符返回一个“单子类型”而不是“匿名”函数的类型。这有助于跟踪我健忘的打字,但并不是很理想。有人有更好的技巧吗?
我喜欢计算表达式,但我会犯一些简单的错误,比如忘记 return 关键字或 ! 关于 let! 然后返回!,或者我只是忘记写do!。状态单子经常发生这种情况,我倾向于忘记状态,只关注我定义的单子运算符。
我有时会确保我的单子运算符返回一个“单子类型”而不是“匿名”函数的类型。这有助于跟踪我健忘的打字,但并不是很理想。有人有更好的技巧吗?
给定一个典型的 monad,如果您缺少!
after 关键字,您的代码不应该编译,因为类型不会起作用。例如:
let sum = async {
let x = async { return 1 }
let y = async { return 2 }
return x + y
}
这不会编译,因为您尝试添加两个Async<int>
s,但如果您将let
s更改为 s,它将编译let!
。
同样,要识别缺失return
的 s,只需注意编译器警告消息和奇怪的单子类型:
let sum = async {
let! x = async { return 1 }
let! y = async { return 2 }
x + y // warning FS0020
}
在这种情况下,sum
是一个Async<unit>
,当您尝试在代码的其他地方使用它时应该很明显。或者,您可以使用类型注释立即捕获此问题:
let sum : Async<int> = async { // error FS0001: type mismatch
let! x = async { return 1 }
let! y = async { return 2 }
x + y // warning FS0020
}