如何将返回 [a] 的函数转换为返回 Monoid 的函数?

How to turn a function returning [a] into a function returning a Monoid?

我正在使用以下函数玩 Haskell return 型多态性:

f :: [a] -> [a]
f [] = mempty
f (x:xs) = [x] <> f xs

显然它什么都不做。我想要做的是修改类型,以便它接受一个列表和 returns 一个 Monoid 容器,其中之一可以是一个列表。我被困在这里是因为 Monoid 采用一种类型参数。我不知道类型是什么:f :: Monoid m => [a] -> ?

这可能吗?

正如您所注意到的,如果没有 a -> m 类型的函数可用,您不能将任意 a 转换为任何特定 Monoid m 的成员。但是没有这样的函数适用于 all Monoid 实例——如果有,它必须在类型类定义中,你可以看到它不存在。

因此,您必须将 f 特化到特定的 Monoid,就像您在此处对 [a] Monoid 所做的那样;或者除了 [a] 之外还接受转换函数 a -> m。也就是说,您的类型可能会变成:

combine :: Monoid m => (a -> m) -> [a] -> m

如果我们 ask Hoogle about this type,我们会看到您的函数已经定义(将列表泛化为 Foldable):

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

您可能会发现实施 foldMap 是一个有用的练习,无论是对于一般的可折叠物还是专门用于列表。

正如 @amalloy 所说,您需要一种方法将列表的内容放入 "monoid container" - Monoid class 没有定义这样的东西,因此您的列表内容需要已经构成一个幺半群(在这种情况下,你的函数只是 mconcat):

f :: Monoid m => [m] -> m
f = mconcat

或者您提供转换器函数(在这种情况下,您将列表的内容转换为您的幺半群,然后执行 mconcat:

f :: Monoid m => (a -> m) -> [a] -> m
f converter = mconcat . fmap converter