【问题标题】:How can I define Pair as a Monoid?如何将 Pair 定义为 Monoid?
【发布时间】:2021-07-09 03:08:27
【问题描述】:

我的数据类型 Pair 定义为

data Pair a b = Pair a b

我想把它做成一个幺半群。这是我的定义。

instance (Monoid a,Monoid b) => Monoid (Pair a b) where
    mempty = Pair mempty mempty
    mappend (Pair x1 y1) (Pair x2 y2) = Pair (mappend x1 x2) (mappend y1 y2)

但是,我收到以下错误。

foldable.hs:3:10: error:
    • Could not deduce (Semigroup (Pair a b))
        arising from the superclasses of an instance declaration
      from the context: (Monoid a, Monoid b)
        bound by the instance declaration at foldable.hs:3:10-49
    • In the instance declaration for ‘Monoid (Pair a b)’
  |
3 | instance (Monoid a,Monoid b) => Monoid (Pair a b) where
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

出了什么问题?

【问题讨论】:

  • 小问题:mappend = (Pair x1 y1) (Pair x2 y2) = ... 中的第一个等号应该被删除。

标签: haskell monoids


【解决方案1】:

mappend 不再是真正的 Monoid 方法。你可以实现它,但它应该只是 (<>) 的同义词,它位于 Monoid 的超类 Semigroup 中。要实现 Monoid,还必须实现 Semigroup,并将 mappend 的定义放在那里,命名为 (<>)

【讨论】:

  • 是的。为了让 OP 清楚,Monoid used 是独立的,但最近通过添加 Semigroup 作为超类来改进标准库。这种改进虽然很好,但不幸的是,它是一个突破性的变化,所以旧的教程和东西可能没有提到这个必要的实现。
【解决方案2】:

将来GHC.Generics 将具有Generically wrapper,它允许派生两个实例via Generically (Pair a b)

{-# Language DeriveGeneric #-}
{-# Language DerivingStrategies #-}
{-# Language DerivingVia #-}

import GHC.Generics

-- >> mempty @(Pair String ())
-- Pair "" ()
--
-- >> Pair "hello" () <> Pair " " undefined <> Pair "world" ()
-- Pair "hello world" ()
data Pair a b
  deriving
  stock Generic

  deriving (Semigroup, Monoid)
  via Generically (Pair a b)

generic-data 已经可以做到这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多