【问题标题】:How to turn a function returning [a] into a function returning a Monoid?如何将返回 [a] 的函数转换为返回 Monoid 的函数?
【发布时间】:2019-06-06 23:38:23
【问题描述】:

我正在使用以下函数使用 Haskell 返回类型多态性:

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

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

这可能吗?

【问题讨论】:

    标签: haskell polymorphism monoids


    【解决方案1】:

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

    因此,您必须将 f 专门用于特定的 Monoid,就像您在此处对 [a] Monoid 所做的那样;否则除了[a] 之外,还接受一个转换函数a -&gt; m。也就是说,你的类型可能变成:

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

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

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

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

    【讨论】:

      【解决方案2】:

      正如@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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-21
        • 2012-05-10
        • 2019-08-31
        • 1970-01-01
        相关资源
        最近更新 更多