11. Monad Proposal
instance 宣言のおさらい
記法
* instance C1 T1 where ...
* instance C1 a => T1 a where ...
* instance C1 a => Cn (T1 a) where ...
型クラスの実装をデータ型に対して与える
23. Foldable
期待される性質
✔ foldr f z t =
appEndo (foldMap (Endo . f) t) z
✔ foldl f z t =
appEndo (getDual (Dual . Endo . flip f) t)) z
✔ fold =
foldMap id
26. Foldable
期待される性質
newtype Endo a = Endo {appEndo :: a -> a}
➜ instance Monoid (Endo a) where
mempty = Endo id
Endo f `mappend` Endo g = Endo (f . g)
28. Foldable
期待される性質
newtype Dual a = Dual {getDual :: a}
➜ instance Monoid a => Monoid (Dual a)
where
mempty = Dual mempty
Dual x `mappend` Dual y =
Dual (x `mappned` y)
29. Foldable
Monoid に期待される性質
✔ mappend mempty x = x
✔ mappend x mempty = x
✔ mappend x (mappend y z) =
mappend (mappend x y) z
✔ mconcat = foldr mappend mempty
35. Foldable
話を戻して Foldable の話
foldr f z t =
appEndo (foldMap (Endo . f) t) z
foldl f z t =
appEndo (getDual (Dual . Endo . flip f) t)) z
要素の畳み方を定義する必要がある
38. Foldable
話を戻して Foldable の話
foldMap :: Monoid m => (a -> m) -> t a -> m
foldMap f = foldr (mappend . f) mempty
Foldable のインスタンスを持つコンテナの要素を
Monoid に型変換させる
39. Foldable
話を戻して Foldable の話
foldr :: (a -> b -> b) -> b -> t a -> b
foldr f z t = appEndo (foldMap (Endo #. f) t) z
コンテナの中身をモノイドのコンテキストに
乗せながら畳んでいく
40. Foldable
話を戻して Foldable の話
foldr :: (a -> b -> b) -> b -> t a -> b
foldr f z t = appEndo (foldMap (Endo #. f) t) z
(´・_・`).oO((#.) ってなんだ?)
41. Foldable
話を戻して Foldable の話
(#.) :: (b -> c) -> (a -> b) -> (a -> c)
(#.) _f = coerce
coerce :: Coercible * a b => a -> b
coerce = let x = x in x
安全かつ強制的に型変換させるための関数
67. OpenGL から見る実装例
Foldable と Traversable はどう実装されているか
instance Foldable TexCoord4
foldr f a (TexCoord4 x y z w) =
x `f` (y `f` (z `f` (w `f` a)))
foldl f a (TexCoord4 x y z w) =
((((a `f` x) `f` y) `f` z) `f` w)
テクスチャ座標の畳込み等(一部抜粋)
68. OpenGL から見る実装例
Foldable と Traversable はどう実装されているか
instance Traversable TexCoord4 where
traverse f (TexCoord4 x y z w) =
pure TexCoord4 <*> f x <*> f y <*> f z
<*> f w
座標変換等(一部抜粋)
82. 文字列の計算量とメモリ使用量
計算量多い(確信)
"Hello"(UTF-8)
: P P P
C# Char#
'H'
P P
C# Char#
'e'
P
C# Char#
'l'
P P P
C# Char#
'l'
P : : : :
⑲
⑱
⑰⑯
⑮⑩⑤
⑭
⑬
⑫⑪
⑨
⑧
⑦⑥
③
②① ㉒㉑ ㉓
④
⑳
1 文字だけでも 4 回以上の計算が…
83. 文字列の計算量とメモリ使用量
メモリ食いすぎィ!
構築子: 1 word
型引数: 1 word / arg
文字列 1 文字分 = 5 words
構築子(:) + ポインタ * 2 + Char のサイズ
1 word 2 words 2 words
C# + Char#
※32bit: 20 bytes, 64bit: 40 bytes
134. 型クラスの表現力を向上する
Flexible Contexts
✔ それ以外は Flexible Instances と同様に書ける
➜ f :: C a b => a -> b -> b
➜ f :: C a a => a -> a -> a
➜ f :: C a (T b) => a -> a -> T b
➜ f :: C a TT => a -> a -> TT