繁体   English   中英

如何编写半群实例?

[英]How to write a Semigroup Instance?

问题

给定数据类型,实现Semigroup实例。 继承人我实施的数据类型: data Or ab = Fst a | Snd b deriving (Eq, Show, Num) data Or ab = Fst a | Snd b deriving (Eq, Show, Num) 它应该像这样运作:

Prelude> Fst 1 <> Snd 2
Snd 2
Prelude> Fst 1 <> Fst 2
Fst 2
Prelude> Snd 1 <> Fst 2
Snd 1
Prelude> Snd 1 <> Snd 2
Snd 1

当我测试像> Fst "help" <> Fst "me"这样的值时,它可以正常工作,但是当我测试其他值时,我会收到错误。 当我尝试通过从错误中派生类来修复这些错误时,我会收到更多错误。 我在这做错了什么?

我的守则

data Or a b =
    Fst a
  | Snd b
  deriving (Eq, Show)

instance (Semigroup a, Semigroup b, Num a, Num b) => Semigroup (Or a b) where
 (Snd a) <> _ = Snd a
  _ <> (Snd a) = Snd a
  (Fst a) <> (Fst b) = Fst b  

错误

当我尝试使用整数> Fst 1 <> Fst 2进行测试时,我得到:

No instance for (Num a0) arising from a use of ‘it’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
  instance RealFloat a => Num (Data.Complex.Complex a)
    -- Defined in ‘Data.Complex’
  instance Data.Fixed.HasResolution a => Num (Data.Fixed.Fixed a)
    -- Defined in ‘Data.Fixed’
  instance forall (k :: BOX) (f :: k -> *) (a :: k).
           Num (f a) =>
           Num (Data.Monoid.Alt f a)
    -- Defined in ‘Data.Monoid’
  ...plus 21 others
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it

当我尝试派生Num类data Or ab = Fst a | Snd b deriving (Eq, Show, Num) data Or ab = Fst a | Snd b deriving (Eq, Show, Num)我得到:

    Can't make a derived instance of ‘Num (Or a b)’:
      ‘Num’ is not a derivable class

    In the data declaration for ‘Or’
Failed, modules loaded: none.

真正的问题是你对你的实例施加的约束,你不需要它。 写吧

instance Semigroup (Or a b) where
  (Snd a) <> _ = Snd a
  _ <> (Snd a) = Snd a
  (Fst a) <> (Fst b) = Fst b

正如chepner所示,您实际上可以减少行数和模式数量,并返回其中一个参数作为结果,而不是构建它的新副本。 这对效率有潜在的好处。

不太重要的是,模式中的括号都是冗余的,因为应用程序具有比任何运算符更高的优先级。

在您的定义中,不需要ab来表示任何特定类型的实例,因为您实际上从未对包装的值执行任何操作。

instance Semigroup (Or a b) where
    (Snd a) <> _ = Snd a
    _       <> (Snd a) = Snd a
    (Fst a) <> (Fst b) = Fst b  

由于您的Or类型与Either同构,因此将其与semigroups包中的Either实例进行比较,该实例同样不会对所涉及的类型施加任何约束。

instance Semigroup (Either a b) where
  Left _ <> b = b
  a      <> _ = a

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM