我试图在Haskell Book(第15章," Monoid,Semigroup")中进行Semigroup练习之一但是我被卡住了。以下是:
newtype Combine a b =
Combine { unCombine :: (a -> b) }
我应该为Semigroup
编写Combine
个实例。
然后书说它必须表现如下:
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
);所以我认为这需要来自<>
的{{1}},但我的代码中已经有Data.Monoid
,因此来自import Data.Semigroup
的{{1}}与<>
中的Data.Monoid
重合1}}。那我该怎么办?
我试图找出如何陈述类似&#34;组合(f Monoid&#39; s&gt; g)&#34;但是无法找到答案。
本书还说明,除非我使用GHC 8.x,否则我必须导入Data.Semigroup
并且我可能会使用&#34; shadow&#34;来自Semigroup
的{{1}};但是我很难找到如何产生这种效果。
有什么想法吗?
答案 0 :(得分:10)
他们想要的可能是添加功能。为此,类型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)
答案 1 :(得分:4)
您可以通过这种方式隐藏Monoid
的{{1}}:
(<>)
然后当你import Data.Monoid hiding ((<>))
时,你的范围只有一个import Data.Semigroup
:来自(<>)
的那个。