4. ナイーブに実装してみる
isBigGang :: Int -> Bool
isBigGang x = x > 9
isBigGang :: Int -> (Bool, String)
isBigGang x =
(x > 9, "Compared gang size to 9")
Thursday, August 22, 13
5. すでに文字列(文脈)のくっ
ついた値を処理するには?
applyLog :: (a, String) ->
(a -> (b, String)) -> (b, String)
applyLog (x, log) f =
let (y, newLog) = f x in
(y, log ++ newLog)
>>= と似た感じ
(>>=) :: m a -> (a -> m b) -> m b
Thursday, August 22, 13
6. applyLogを使ってみる
•ログが連結される
•関数は文脈なしの値を引数にとる
> (3, "abc") `applyLog` isBigGang
(False, "abcCompared gang size to 9")
> ("Tobin", "Got outlaw name.") `applyLog`
(x -> (length x, "Applied length.")
(5, "Got out lawname. Applied length.")
Thursday, August 22, 13
8. モノイドを使って
書き換えてみる
applyLog :: (Monoid m) =>
(a,m)->(a->(b,m))->(b,m)
applyLog (x, log) f =
let (y, newLog) = f x in
(y, log `mappend` newLog)
「値+ログ」から「値+モノイド値」に
拡張された
Thursday, August 22, 13
9. 食べ物を与えると
飲み物+値段が返る関数
import Data.Monoid
type Food = String
type Price = Sum Int
addDrink :: Food -> (Food, Price)
addDrink "beans" = ("milk", Sum 25)
addDrink "jerky" = ("whiskey", Sum 99)
addDrink _ = ("beer", Sum 30)
モノイドは値に計算が
定義されているのがいいね
Thursday, August 22, 13
10. 「食べ物+値段」に
addDrinkを適用すると..
> ("beans", Sum 10) `applyLog` addDrink
("milk,Sum {getSum=35})
> ("dogmeat", Sum 5) `applyLog` addDrink
("beer",Sum {getSum=35})
> ("dogmeat", Sum 5) `applyLog` addDrink
`applyLog` addDrink
("beer",Sum {getSum=65})
おまけの値はログに限らないことがはっきりした
Thursday, August 22, 13
12. Writer w a の定義
newtype Writer w a =
Writer{runWriter::(a,w)}
タプルをラップした型
a が主な値の型
wがおまけのモノイド値の型
Writer値コンストラクタは非公開
代わりにwriter関数が公開
Thursday, August 22, 13
13. Writer w a の
Monadインスタンス
instance (Monoid w) => Monad (Writer w) where
return x = Writer (x, mempty)
(Writer (x, v)) >>= f =
let (Writer (y, v')) = f x in
Writer (y, v `mappend` v')
>>= と自分で定義した applyLog は
タプルがラップされている以外は同じ
Thursday, August 22, 13