mempty 有不同的定义取决于 mempty 是左还是右 arg?
mempty with different definition depending on whether mempty is left or right arg?
我有以下数据类型和半组实例:
data Or a b =
Fst a
| Snd b deriving (Eq, Show)
instance Semigroup (Or a b) where
(<>) (Fst a) (Fst b) = Fst b
(<>) (Snd a) (Fst b) = Snd a
(<>) (Fst a) (Snd b) = Snd b
(<>) (Snd a) (Snd b) = Snd a
我想为上面的类型创建一个幺半群实例,但我不知道该怎么做。如果我使用下面的定义
instance (Monoid a, Monoid b) => Monoid (Or a b) where
mempty = (Fst mempty)
mappend = (<>)
它适用于 <>
的所有输入对,除了我 mappend
(Fst a) <> mempty
计算结果为 mempty
。
如何解决这个问题,使 mempty
有效?似乎没有一些新的语法或概念就无法完成,因为它取决于 mempty 是在左边还是右边...
有一个非常好的(和更简单的)半群,它总是采用第一个参数:
newtype FirstS a = FirstS a
instance Semigroup (FirstS a) where
a <> b = a
不幸的是,它不是幺半群,因为——除了包装类型的微不足道的选择——这个操作没有左标识。标准 First
类型通过添加可区分的标识元素来修补 FirstS
,因此:
newtype First a = First (Maybe a)
instance Semigroup (First a) where
First Nothing <> b = b
a <> First Nothing = a
a <> b = a -- this clause is exactly as before
那么选择mempty = First Nothing
就很容易编写Monoid
实例了。您可以通过向您的类型添加可区分的标识元素来使用类似的技巧:
data Or a b = Fst a | Snd b | Neither
instance Semigroup (Or a b) where
Neither <> b = b
a <> Neither = a
-- the remainder of the clauses are as before
这使得 mempty = Neither
的选择变得非常容易。
这个模式非常有用,它实际上在 semigroups
中有一个新类型包装器,所以你也可以使用你原来的 Or a b
类型来编写这个补丁类型,就像 Option (Or a b)
并免费获得 Semigroup
和 Monoid
个实例。
我有以下数据类型和半组实例:
data Or a b =
Fst a
| Snd b deriving (Eq, Show)
instance Semigroup (Or a b) where
(<>) (Fst a) (Fst b) = Fst b
(<>) (Snd a) (Fst b) = Snd a
(<>) (Fst a) (Snd b) = Snd b
(<>) (Snd a) (Snd b) = Snd a
我想为上面的类型创建一个幺半群实例,但我不知道该怎么做。如果我使用下面的定义
instance (Monoid a, Monoid b) => Monoid (Or a b) where
mempty = (Fst mempty)
mappend = (<>)
它适用于 <>
的所有输入对,除了我 mappend
(Fst a) <> mempty
计算结果为 mempty
。
如何解决这个问题,使 mempty
有效?似乎没有一些新的语法或概念就无法完成,因为它取决于 mempty 是在左边还是右边...
有一个非常好的(和更简单的)半群,它总是采用第一个参数:
newtype FirstS a = FirstS a
instance Semigroup (FirstS a) where
a <> b = a
不幸的是,它不是幺半群,因为——除了包装类型的微不足道的选择——这个操作没有左标识。标准 First
类型通过添加可区分的标识元素来修补 FirstS
,因此:
newtype First a = First (Maybe a)
instance Semigroup (First a) where
First Nothing <> b = b
a <> First Nothing = a
a <> b = a -- this clause is exactly as before
那么选择mempty = First Nothing
就很容易编写Monoid
实例了。您可以通过向您的类型添加可区分的标识元素来使用类似的技巧:
data Or a b = Fst a | Snd b | Neither
instance Semigroup (Or a b) where
Neither <> b = b
a <> Neither = a
-- the remainder of the clauses are as before
这使得 mempty = Neither
的选择变得非常容易。
这个模式非常有用,它实际上在 semigroups
中有一个新类型包装器,所以你也可以使用你原来的 Or a b
类型来编写这个补丁类型,就像 Option (Or a b)
并免费获得 Semigroup
和 Monoid
个实例。