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

时间:2010-04-06 23:44:03

标签: haskell map

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

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

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

即。

之类的东西

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

f : a-> b

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

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

2 个答案:

答案 0 :(得分:15)

如果f正在调用云,那么f无疑会使用某些monad,可能是IO monad或者来自IO monad的monad 。有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

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

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

如果您希望将所有错误一起返回,并且所有成功结合在一起,则可以使用lefts中的rightsData.Either函数。

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构造函数的原因实际上更深(因为这意味着我们可以使用修改正确的Either类型创建一个仿函数结果,这是Left构造函数无法实现的。)

答案 1 :(得分:2)

您可以写下g以返回Maybe monad

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

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