应用可能无法列表中所有值的函数

Egw*_*wor 3 haskell map

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

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

目前,我的包裹功能的响应对象f有错误对,我可以再有效unzip之后

即类似的东西

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

f : a-> b

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

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

Die*_*Epp 15

如果f是打电话给云,那么f无疑是使用一些monad,可能是IOmonad或者monad派生的IOmonad.有monadic版本的map.以下是您通常会做的第一次尝试:

f :: A -> IO B -- defined elsewhere
g :: [A] -> IO [B]
g xs = mapM f xs
-- or, in points-free style:
g = mapM f
Run Code Online (Sandbox Code Playgroud)

这有(可能)不良属性g将失败,如果任何调用失败,则不返回任何值f.我们通过使它f返回答案或错误消息来解决这个问题.

type Error = String
f :: A -> IO (Either Error B)
g :: [A] -> IO [Either Error B]
g = mapM f
Run Code Online (Sandbox Code Playgroud)

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

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

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

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