异常单子的F#计算表达式

异常单子的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

我正在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 -> 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)