2016-09-12 6 views
2

私はHaskell Book(第15章「Monoid、Semigroup」)でSemigroup演習の1つをしようとしていますが、私は立ち往生しています。このデータ型の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) 

:そして、私の考えは、擬似コードでは、次のようなもの、であるfgを追加、その具体的な付加操作が何であれ(それはfgによって異なります)。だから私はこれがからData.Monoidまで必要と思うが、私はすでにimport Data.Semigroupを自分のコードに持っているので、<>からData.MonoidData.Semigroupのものと一致する。では私は何をすべきですか?

私は「Combine(f Monoid's <> g)」のように何かを述べることができましたが、見つけられませんでした。

GHC 8.xを使用していない限り、私はSemigroupをインポートする必要があります。<>からMonoidに「shadow」がある可能性があります。しかし、私はこの影響をどのようにして見つけるか苦労しています。

アイデア?

答えて

8

彼らが望むのはおそらく関数の追加です。そのため、タイプ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) 
+0

したがって、結合のSemigroupインスタンスのみを書き込むことはできませんか?私はMonoidを余儀なくされましたか?私は少し混乱しています。 –

+3

@EmreSevinçCombineは実際にはセミグループになることができ、2番目の値だけがセミグループになる必要があります(インスタンスVには 'mempty 'は呼び出されません)。 –

+0

本当に、私は 'Semigroup b'だけで答えを更新しました –

4

シャドウできMonoid(<>)この方法:あなたimport Data.Semigroupは、あなただけの1 (<>)範囲内になります次に

import Data.Monoid hiding ((<>)) 

: 1つはData.Semigroupです。

+0

ありがとう!それを学ぶのは良い! (それは既にLispのように手数料がかかり始めました:P) –

関連する問題