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

时间:2019-06-06 23:38:23

标签: haskell polymorphism monoids

我正在使用以下功能处理Haskell返回类型多态性:

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

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

这可能吗?

2 个答案:

答案 0 :(得分:9)

您注意到,如果没有可用的类型a的函数,就不能将任意m转换为任何特定Monoid a -> m的成员。但是没有这样的函数可用于 all 所有Monoid实例-如果存在,则必须在typeclass定义中,并且您会发现它不存在。

因此,您必须像专门针对f Monoid那样将[a]专用于特定的Monoid;否则,除了a -> m之外,还接受转换函数[a]。也就是说,您的类型可能变为:

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

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

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

对于一般的折叠式或专用于列表的折叠式而言,实施foldMap可能都是有用的练习。

答案 1 :(得分:3)

正如@amalloy所说,您需要一种将列表内容放入“ monoid容器”的方法-Monoid类未定义此类内容,因此列表的内容需要已经构成了monoid(在在这种情况下,您的功能只是mconcat):

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

或提供一个转换器函数(在这种情况下,您将列表的内容转换为半身像,然后做mconcat:

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