结合两个任一个 Monad 的结果

Sat*_*mar 2 haskell functional-programming

你如何在 Haskell 中处理这种情况(下面提供的伪代码)?

 x = somethingThatReturnsMaybe(s1)
 y = somethingThatReturnsMaybe(s2)

 if(x == Nothing) return Left "invalid x"
 if(y == Nothing) return Left "invalid y"

 callFn(fromJust(x), fromJust(y));

Run Code Online (Sandbox Code Playgroud)

我可以想到两种方法:-

  1. 从调用处传递Maybes,这样上面的代码就可以包装在一个函数中,我可以在函数绑定/定义中使用模式匹配。
  2. 我已经编写了这段代码来使用任一组合这些值
mapToRight (\(x, y) -> callFn x y) combined_values
                where { combined_values = (maybeToRight "Invalid x!" x >>= combiner) <*>
                                        maybeToRight "Invalid target position" y;
                mapToRight = second; x = somethingThatReturnsMaybe s1; y = somethingThatReturnsMaybe s2
                }

Run Code Online (Sandbox Code Playgroud)

对于第二个选项,我有以下组合器

combiner :: b -> Either a (b0 -> (b, b0));
combiner x = Right (x,)

maybeToRight :: a -> Maybe b -> Either a b
maybeToRight a Nothing = Left a
maybeToRight a (Just x) = Right x
Run Code Online (Sandbox Code Playgroud)

这两者之间是否有任何偏好(虽然第一个对我来说不太可取,因为它可能涉及更多的变化),或者有没有更好的选择?

Dan*_*ner 7

我会导入Control.Error,然后写这个:

do
    x <- note "invalid x" (somethingThatReturnsMaybe s1)
    y <- note "invalid y" (somethingThatReturnsMaybe s2)
    callFn x y
Run Code Online (Sandbox Code Playgroud)

note是您的maybeToRight. 的Either的的实现(>>=)是处理解缠/组合。

  • +1,我不知道“note”。鉴于它的字面意义是“注意 a = 也许(左 a)右”,人们可能会质疑它是否如此接近 [Fairbairn 阈值](https://wiki.haskell.org/Fairbairn_threshold),以至于更容易使用“maybe”而不是导入“Control.Error”... (3认同)