5

由于network-api-support包,我刚刚发现了 Endo 类型,并且我发现需要能够将 Maybe 值放入 Endo 中。因此,我编写了一个名为 MaybeEndo 的函数。这是一个使用它的例子:

setProxy :: Proxy -> RequestTransformer
setProxy (Proxy pHost pPort) = Endo $ addProxy pHost pPort

maybeEndo :: (a -> Endo b) -> Maybe a -> Endo b
maybeEndo _ Nothing = Endo id
maybeEndo f (Just v) = f v

setPotentialProxy :: Maybe Proxy -> RequestTransformer
setPotentialProxy = maybeEndo setProxy

令我印象深刻的是,这似乎应该已经封装到某种类型的模式中。

4

2 回答 2

12

你已经找到了maybe (Endo id)。ButEndo 是 的一个实例Monoid,并且Endo id是它的中性元素mempty。所以你也可以写得更笼统

maybeMonoid :: Monoid b => (a -> b) -> Maybe a -> b
maybeMonoid = maybe mempty

这已经是非常惯用的了(当你用 google 搜索时会有很多点击"maybe mempty")。通过使用以下函数,您可以更加通用Data.Foldable

foldMap :: (Foldable t, Monoid b) => (a -> b) -> t a -> b

所以有了这个,你可以写

setPotentialProxy :: Maybe Proxy -> RequestTransformer
setPotentialProxy = foldMap setProxy

(但请确保您留下类型签名,否则您将在以后阅读代码时花费太多时间来弄清楚它:-))。

于 2014-10-25T09:33:13.003 回答
0

当我写这个问题时,我想到了一个解决方案:

maybeEndo :: (a -> Endo b) -> Maybe a -> Endo b
maybeEndo = maybe (Endo id)

这意味着 setPotentialProxy 可能只是:

setPotentialProxy :: Maybe Proxy -> RequestTransformer
setPotentialProxy = maybe (Endo id) setProxy

但是,我仍然决定发布这个问题,因为也许有一种更自然的方式来处理这种情况。也许它会帮助别人。

于 2014-10-25T09:03:22.667 回答