haskell – 如何为此数据类型编写Semigroup实例?

我试图在Haskell Book(第15章,“Monoid,Semigroup”)中进行Semigroup练习之一,但我被卡住了.给出以下内容:

newtype Combine a b =
  Combine { unCombine :: (a -> b) }

我应该为Combine编写Semigroup实例.

然后书说它必须表现如下:

 Prelude> let f = Combine $\n -> Sum (n + 1)
 Prelude> let g = Combine $\n -> Sum (n - 1)
 Prelude> unCombine (f <> g) $0
 Sum {getSum = 0}
 Prelude> unCombine (f <> g) $1
 Sum {getSum = 2}
 Prelude> unCombine (f <> f) $1
 Sum {getSum = 4}
 Prelude> unCombine (g <> f) $1
 Sum {getSum = 2}

所以我首先开始使用类型检查的错误解决方案:

instance Semigroup (Combine a b) where
  Combine f <> Combine g = Combine f

这当然不是预期的,但希望朝着正确的方向迈出一步.在伪代码中,我的想法类似于以下内容:

 instance Semigroup (Combine a b) where
   (Combine f) <> (Combine g) = Combine (SOMETHING)

SOMETHING是:f和g附加,无论具体的附加操作是什么(它取决于f和g);所以我认为这需要<>从Data.Monoid,但我已经在我的代码中导入Data.Semigroup,因此<>来自Data.Monoid与Data.Semigroup中的一致.那我该怎么办?

我试图找出我怎么说“Combine(f Monoid’s<> g)”这样的东西,但是找不到.

本书还说明,除非我使用的是GHC 8.x,否则我必须导入Semigroup并且我可能会对“<>来自Monoid;但我很难找到如何产生这种效果.

有任何想法吗?

最佳答案
他们想要的可能是增加功能.为此,类型b需要是半群:

import Data.Semigroup

newtype Combine a b =
  Combine { unCombine :: (a -> b) }

instance Semigroup b => Semigroup (Combine a b) where
  (Combine f) <> (Combine g) = Combine (\x -> f x <> g x)

转载注明原文:haskell – 如何为此数据类型编写Semigroup实例? - 代码日志