异常单子的F#计算表达式
我正在F#中实现一个异常monad。首先,我采用了一种ML方法,该方法有效:异常单子的F#计算表达式,f#,monads,F#,Monads,我正在F#中实现一个异常monad。首先,我采用了一种ML方法,该方法有效: module ExceptionMonad = type exception_ = string type 'a t = Raise of exception_ | Return of 'a let return' t = Return t let raise' e = Raise e let (>>=) m k = match m with | Raise e -&g
module ExceptionMonad =
type exception_ = string
type 'a t = Raise of exception_ | Return of 'a
let return' t = Return t
let raise' e = Raise e
let (>>=) m k =
match m with
| Raise e -> Raise e
| Return a -> k a
module TestExceptionMonad =
open ExceptionMonad
let test_exception_monad =
begin
return' 1 >>= fun a ->
return' 0 >>= fun b ->
if b = 0
then raise' "divide by zero"
else return' (a / b)
end (* => raise' "divide by zero" *)
现在我尝试使用F#计算表达式:
type exception_ = string
type 'a exception_monad = Raise of exception_ | Return of 'a
type ExceptionMonad() =
member x.Bind(m, k) =
match m with
| Raise e -> Raise e
| Return a -> k a
member x.Return(t) = Return t
member x.Zero() = Return 0
module TestExceptionMonad =
let monad = new ExceptionMonad()
let test_exception_monad =
monad {
let! a = Return 1 in
let! b = Return 0 in
if b = 0 then
Raise "divide by zero"
else
return (a / b)
} (* => Raise "divide by zero" *)
但F#抱怨表达式Raise“除以零”
属于unit
类型。这是不正确的,但我猜在幕后会有一些代码生成,错误就是指这个。我也不确定为什么需要x.Zero()
,但编译器需要它。在F#计算表达式中,当您有一个要从计算中返回的“一元值”时,您需要使用返回代码>构造:
if b = 0 then return! Raise "divide by zero"
else return (a / b)
要支持此功能,还需要将ReturnFrom
添加到计算生成器中:
member x.ReturnFrom(c) = c
也就是说,如果您想了解计算生成器在F#中的工作方式,那么为异常实现计算生成器是一个很好的练习。但是,除非你有很好的理由想要它,否则我不会在实践中推荐它。F#已经直接支持可以使用的异常,而无需任何特殊语法,这种语法在大多数情况下都能很好地工作,因此确实没有必要用更复杂的方法来代替它
如果您正在寻找输入验证(与普通异常处理相反),那么有一个很好的F#项目可以实现这方面的计算,但同样-这更像是输入验证而不是异常处理。在F#计算表达式中,当您有一个“一元值”要从计算返回时,您需要使用返回代码>构造:
if b = 0 then return! Raise "divide by zero"
else return (a / b)
要支持此功能,还需要将ReturnFrom
添加到计算生成器中:
member x.ReturnFrom(c) = c
也就是说,如果您想了解计算生成器在F#中的工作方式,那么为异常实现计算生成器是一个很好的练习。但是,除非你有很好的理由想要它,否则我不会在实践中推荐它。F#已经直接支持可以使用的异常,而无需任何特殊语法,这种语法在大多数情况下都能很好地工作,因此确实没有必要用更复杂的方法来代替它
如果您正在寻找输入验证(与普通的异常处理相反),那么有一个很好的F#项目可以实现这方面的计算,但同样-这更像是一个输入验证而不是异常处理。您需要使用其中一个碰撞操作来执行一元操作。即返回代码>,让我来代码>或执行代码>。在这种情况下,您可以写:
if b = 0 then
return! Raise "divide by zero"
else
return (a / b)
您需要使用其中一个碰撞操作来执行一元操作。即返回代码>,让我来代码>或执行代码>。在这种情况下,您可以写:
if b = 0 then
return! Raise "divide by zero"
else
return (a / b)