3

有没有办法用镜头写下以下内容......

[Maybe Text] -> Text

...这可能可以概括为:

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

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

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

PS:我假设镜头有一些时髦的组合器来做到这一点。如果我被镜头的美妙所蒙蔽,而这可以通过更简单的组合器轻松实现,请告诉我。

4

3 回答 3

7

您的(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
""
于 2019-09-18T11:42:25.230 回答
7

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

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

事实上,fold = maybe mempty id = fromMaybe mempty对于Maybe,所以它真的是一样的。

它的一般类型是:

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

这完全适用于[Maybe a].


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

foldMap fold

在这里,在用空字符串替换 s 时fold删除Just包装器。Nothing然后,foldMap连接所有结果字符串。

于 2019-09-18T12:09:34.537 回答
4

答案只是一个折叠,所以你可以用一种愚蠢的方式“使用镜头”foldOf

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

所以如果你能找到 a myFold :: Fold (t a) a,你可以用它foldOf来获得:

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

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

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

foldOf folded :: (Foldable t, Monoid a) => t a -> a
于 2019-09-18T21:50:22.337 回答