【问题标题】:Applying a function that may fail to all values in a list将可能失败的函数应用于列表中的所有值
【发布时间】:2010-04-06 23:44:03
【问题描述】:

我想将函数 f 应用于值列表,但是函数 f 可能会随机失败(它实际上是在调用云中的服务)。

我想我想使用map 之类的东西,但我想将该函数应用于列表中的所有元素,然后我想知道哪些失败了,哪些成功了。

目前我正在用错误对包装函数 f 的响应对象,之后我可以有效地 unzip

即像

g : (a->b) -> a -> [ b, errorBoolean]

f : a-> b

然后运行代码...map g (xs)

有没有更好的方法来做到这一点?另一种替代方法是遍历数组中的值,然后返回一对数组,一个列出成功的值,一个列出失败的值。对我来说,这似乎应该是相当普遍的事情。或者,我可以返回一些特殊值。处理这个问题的最佳做法是什么?

【问题讨论】:

  • 仅供参考:Haskell 中的列表必须是同质的(即只能包含一种类型的东西)。在您的情况下,您需要返回一个元组(b, Bool)。当然正确的方法是使用 Maybe 或 Either。

标签: haskell map


【解决方案1】:

如果f 正在调用云,那么f 无疑是在使用一些单子,可能是IO 单子或从IO 单子派生的单子。 map 有 monadic 版本。这是您通常会做的第一次尝试:

f :: A -> IO B -- defined elsewhere
g :: [A] -> IO [B]
g xs = mapM f xs
-- or, in points-free style:
g = mapM f

如果对f 的任何调用失败,这具有(可能)不受欢迎的属性,g 将失败,不返回任何值。我们通过使 f 返回答案或错误消息来解决此问题。

type Error = String
f :: A -> IO (Either Error B)
g :: [A] -> IO [Either Error B]
g = mapM f

如果您希望将所有错误一起返回,并将所有成功聚集在一起,您可以使用Data.Either 中的leftsrights 函数。

h :: [A] -> IO ([B], [Error])
h xs = do ys <- g xs
          return (rights ys, lefts ys)

如果您不需要错误消息,只需使用Maybe B 而不是Either Error B

Either 数据类型是表示可能导致错误或正确值的值的最常用方式。错误使用Left 构造函数,正确值使用Right 构造函数。作为奖励,“right”在英语中也意味着“正确”,但是正确的值使用Right构造函数的原因实际上更深(因为这意味着我们可以从修改正确结果的Either类型创建一个仿函数,这在 Left 构造函数上是不可能的)。

【讨论】:

    【解决方案2】:

    你可以写你的g来返回一个Maybe monad

    f: a -> b
    g: (a -> b) -> a -> Maybe b
    

    如果f失败,g返回Nothing,否则返回Just (f x)

    【讨论】:

      猜你喜欢
      • 2017-05-01
      • 2020-02-18
      • 1970-01-01
      • 2019-08-28
      • 2013-11-15
      • 1970-01-01
      • 2016-04-01
      • 2015-08-25
      • 1970-01-01
      相关资源
      最近更新 更多