型によるプログラミング 合成によるデザイン SemigroupとMonoid データ型、リファクタリング、インスタンス
入門Haskellプログラミング (Will Kurt(著)、株式会社クイープ(監修、翻訳)、翔泳社)のUNIT3(型によるプログラミング)、LESSON 17(合成によるデザイン:SemigroupとMonoid)、17.5(練習問題)Q17-2の解答を求めてみる。
コード
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 cycledL2
where nToAdd = length l2
repeatedL1 = map (take nToAdd . repeat) l1
newL1 = mconcat repeatedL1
cycledL2 = cycle l2
combineEvents :: Events -> Events -> Events
combineEvents (Events e1) (Events e2) = Events (cartCombine combiner e1 e2)
where combiner = \x y -> mconcat [x, "-", y]
combineProbs :: Probs -> Probs -> Probs
combineProbs (Probs p1) (Probs p2) = Probs (cartCombine (*) p1 p2)
instance Semigroup Events where
(<>) = combineEvents
instance Monoid Events where
mempty = Events []
mappend = (<>)
instance Semigroup Probs where
(<>) = combineProbs
instance Monoid Probs where
mempty = Probs []
mappend = (<>)
events1 :: Events
events1 = Events ["heads", "tails"]
events2 :: Events
events2 = Events ["red", "blue", "green"]
probs1 :: Probs
probs1 = Probs [0.5, 0.5]
probs2 :: Probs
probs2 = Probs [0.1, 0.2, 0.7]
入出力結果(Terminal, Zsh)
% ghci
GHCi, version 8.10.5: https://www.haskell.org/ghc/ :? for help
macro 'doc' overwrites builtin command. Use ':def!' to overwrite.
(0.00 secs, 0 bytes)
(0.00 secs, 0 bytes)
Loaded GHCi configuration from /.../.ghc/ghci.conf
Prelude
λ> :load sample2
[1 of 1] Compiling Main ( sample2.hs, interpreted )
Ok, one module loaded.
(0.14 secs,)
*Main
λ> mappend events1 events2
Events ["heads-red","heads-blue","heads-green","tails-red","tails-blue","tails-green"]
it :: Events
(0.01 secs, 137,832 bytes)
*Main
λ> mappend probs1 probs2
Probs [5.0e-2,0.1,0.35,5.0e-2,0.1,0.35]
it :: Probs
(0.01 secs, 101,632 bytes)
*Main
λ> :quit
Leaving GHCi.
%