我想将一个函数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)
如果您希望将所有错误一起返回,并且所有成功聚集在一起,您可以使用lefts和rights函数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构造函数上).