如何将 [Maybe Text] 与镜头连接起来?

How to concatenate [Maybe Text] with lenses?

有没有办法用镜头写出下面的...

[Maybe Text] -> Text

...大概可以归纳为:

(Monoid a, Traversable t) => t a -> a

我正在尝试做的具体示例:

[Just "abc", Nothing, Just "def"] -> "abcdef"
[Nothing, Nothing] -> ""

PS:我假设镜头有一些时髦的组合器可以做到这一点。如果我对镜头的出色表现感到措手不及,而这可以通过更简单的组合器轻松实现,请告诉我。

您的 (Monoid a, Traversable t) => t a -> a 函数可以进一步概括为简单的 fold :: (Foldable f, Monoid a) => f a -> a

例如:

Prelude> import Data.Foldable
Prelude Data.Foldable> fold [Just "abc", Nothing, Just "def"]
Just "abcdef"

我们可以将它从 Maybe 中解包出来:

import Data.Foldable(fold, mempty)
import Data.Maybe(maybe)

foldMaybe :: (Foldable f, Monoid a) => f (Maybe a) -> a
foldMaybe = fromMaybe mempty . fold

例如:

Prelude Data.Foldable Data.Maybe> foldMaybe [Just "abc", Nothing, Just "def"]
"abcdef"
Prelude Data.Foldable Data.Maybe> foldMaybe [Nothing] :: String
""

作为 Willem 解决方案的变体,我更喜欢双 fold(一个用于列表,另一个用于 Maybe):

> fold . fold $ [Just "abc", Nothing, Just "def"]
"abcdef"

其实fold = maybe mempty id = fromMaybe memptyMaybe,所以真的是一样的

它的一般类型是:

fold . fold :: (Monoid a, Foldable t1, Foldable t2, Monoid (t1 a)) => t2 (t1 a) -> a

完全适用于 [Maybe a].


@dfeuer 在下面建议的另一个不错的解决方案:

foldMap fold

此处,fold 删除了 Just 包装器,同时将 Nothing 替换为空字符串。然后,foldMap 连接所有结果字符串。

答案只是一个折叠,所以你可以 "use lenses" 以一种愚蠢的方式使用 foldOf

foldOf :: Monoid a => Fold s a -> s -> a

所以如果你能找到一个 myFold :: Fold (t a) a,你可以将它与 foldOf 一起使用以获得:

foldOf myFold :: Monoid a => t a -> a

幸运的是,对于 Foldable t 的任何实例,我们都可以访问 folded :: Fold (t a) a。所以我们可以使用 foldOffolded:

foldOf :: Monoid a => Fold s a -> s -> a
folded :: Foldable t => Fold (t a) a

foldOf folded :: (Foldable t, Monoid a) => t a -> a