計算機科学のブログ

Haskell - 型によるプログラミング - 合成によるデザイン:SemigroupとMonoid - リファクタリング

入門Haskellプログラミング (Will Kurt(著)、株式会社クイープ(監修、翻訳)、翔泳社)の UNIT3(型によるプログラミング)、LESSON 17(合成によるデザイン:SemigroupとMonoid)、17.5(練習問題)、Q17-2の解答を求めてみる。

コード

sample.hs

import Distribution.PackageDescription.Quirks (patchQuirks)

main :: IO ()
main = do
  print $ coinEvents <> coinEvents
  print $ coinProbs <> coinProbs
  print $ spinnerEvents <> spinnerEvents
  print $ spinnerProbs <> spinnerProbs
  print $ coinEvents <> spinnerEvents
  print $ coinProbs <> spinnerProbs
  print $ spinnerEvents <> coinEvents
  print $ spinnerProbs <> coinProbs

data Events = Events [String] deriving (Show)

data Probs = Probs [Double] deriving (Show)

cartCombine :: (a -> b -> c) -> [a] -> [b] -> [c]
cartCombine func l1 l2 = zipWith func newL1 cycleL2
  where
    nToAdd = length l2
    repeatedL1 = map (replicate nToAdd) l1
    newL1 = mconcat repeatedL1
    cycleL2 = cycle l2

instance Semigroup Events where
  (<>) :: Events -> Events -> Events
  (<>) (Events e1) (Events e2) = Events $ cartCombine combiner e1 e2
    where
      combiner x y = mconcat [x, "-", y]

instance Monoid Events where
  mempty :: Events
  mempty = Events []

instance Semigroup Probs where
  (<>) :: Probs -> Probs -> Probs
  (<>) (Probs p1) (Probs p2) = Probs $ cartCombine (*) p1 p2

instance Monoid Probs where
  mempty :: Probs
  mempty = Probs []

coinEvents :: Events
coinEvents = Events ["heads", "tails"]

coinProbs :: Probs
coinProbs = Probs [0.5, 0.5]

spinnerEvents :: Events
spinnerEvents = Events ["red", "blue", "green"]

spinnerProbs :: Probs
spinnerProbs = Probs [0.1, 0.2, 0.7]

入出力結果(Terminal, Zsh)

% runghc sample.hs
Events ["heads-heads","heads-tails","tails-heads","tails-tails"]
Probs [0.25,0.25,0.25,0.25]
Events ["red-red","red-blue","red-green","blue-red","blue-blue","blue-green","green-red","green-blue","green-green"]
Probs [1.0000000000000002e-2,2.0000000000000004e-2,6.999999999999999e-2,2.0000000000000004e-2,4.000000000000001e-2,0.13999999999999999,6.999999999999999e-2,0.13999999999999999,0.48999999999999994]
Events ["heads-red","heads-blue","heads-green","tails-red","tails-blue","tails-green"]
Probs [5.0e-2,0.1,0.35,5.0e-2,0.1,0.35]
Events ["red-heads","red-tails","blue-heads","blue-tails","green-heads","green-tails"]
Probs [5.0e-2,5.0e-2,0.1,0.1,0.35,0.35]
%