Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Haskell超初心者勉強会14

593 views

Published on

  • Be the first to comment

  • Be the first to like this

Haskell超初心者勉強会14

  1. 1. Haskell超初心者勉強会 14 すごいHaskell 第12章: モノイド (前編)
  2. 2. 今回の内容 •newtype •Monoid とは •いろんな Monoid
  3. 3. Monoid ...? •「二項演算子で結合できるような型」
  4. 4. でもその前に、、 newtype •「1つの型を取り、それを何かにくるん で別の型にみせかけたい」 data ZipList a = ZipList { getZipList :: [a] } newtype ZipList a = ZipList { getZipList :: [a] }
  5. 5. newtype の利点・欠点 • 利点 • 速い。包んだり戻したりの処理を省略。 • 欠点 • 値コンストラクタが1種類だけ • 値コンストラクタがとれるフィールドが ひとつだけ
  6. 6. newtypeでの 型クラス導出(deriving) •deriving で導出出来る •くるまれている型が導出しようとして いる型クラスのインスタンスでなけれ ばならない
  7. 7. newtypeでの 型クラスのインスタンス作成 • タプルをFunctorにしたい • fmap では f を第一要素に効かせたい • タプルは型コンストラクタが2つ型を取る • 1つだけ指定できない (関数は出来たのに) • newtype で包む newtype Pair b a = Pair { getPair :: (a, b) } instance Functor (Pair c) where fmap f (Pair (x, y)) = Pair (f x, y)
  8. 8. こんな感じ newtype Pair b a = Pair { getPair :: (a, b) } instance Functor (Pair c) where fmap f (Pair (x, y)) = Pair (f x, y) > getPair $ fmap (*100) (Pair (2, 3)) (200,3) > getPair $ fmap reverse (Pair (“london”, 3)) ("nodnol",3)
  9. 9. newtypeの パターンマッチ (1) data CoolBool = CoolBool { getCoolBool :: Bool } helloMe :: CoolBool -> String helloMe (CoolBool _) = "Hello" main = putStrLn $ helloMe undefined 評価するとエラーになる値 ここでエラーが起きる
  10. 10. newtypeの パターンマッチ (2) newtype CoolBool = CoolBool {getCoolBool :: Bool} helloMe :: CoolBool -> String helloMe (CoolBool _) = "Hello" main = putStrLn $ helloMe undefined エラーにならない! 値コンストラクタが1つしか存在しな いので引数を評価せずマッチできる
  11. 11. type, newtype, dataの 整理 •type -- 型の別名 (実際は同じ型) •newtype -- 包んだ別の型を作る。値コ ンストラクタは1つだけ。フィールド1 つだけ。速い。 •data -- 新しい型を作る
  12. 12. type, newtype, dataの 使い所 •type -- 型シグネチャを整理したい。名 が体を表すようにしたい。 •newtype -- 既存型をある型クラスのイ ンスタンスにしたい。新しい型に包み たい。 •data -- 新しい型を作りたい
  13. 13. 余談: Scala 2.10 で 導入された value class • 1つの値をwrapする • コンパイル時は違う型 • 基本的に実行時は型変換されない • pattern match とかしようとすると 実行時に型変換される class Wrapper(val underlying: Int) extends AnyVal { def foo: Wrapper = new Wrapper(underlying * 19) }
  14. 14. ○ ○ = ○ • (* と 1)、(++ と []) に共通の性質は? • 関数は引数を2つとる • 2引数と戻り値の型は等しい • 相手を変えない特別な値がある(1, []) • 結合的である (a * b) * c = a * (b * c) →これが Monoid
  15. 15. Monoid とは •結合的な二項演算子 と 単位元 •* と 1 •++ と [] •+ と 0 •他にも無数の Monoid
  16. 16. Monoid 型クラス class Monoid m where mempty :: m mappend :: m -> m -> m mconcat :: [m] -> m mconcat = foldr mappend mempty mは具体型 単位元(多相定数) 関数
  17. 17. Monoid則 •プログラマの責任! 1) mempty `mappend` x = x 2) x `mappend` mempty = x 3) (x `mappend` y) `mappend` z = x `mappend` (y `mappend` z)
  18. 18. ここからいろんな Monoid を見ていきます
  19. 19. ListはMonoid x `mappend` y = y `mappend` x は満たさなくて良い instance Monoid [a] where mempty = [] mappend = (++) Monoid [] ではないことに注意
  20. 20. 数をMonoidに instance Num a => Monoid a where mempty = 1 mappend = (*) instance Num a => Monoid a where mempty = 0 mappend = (+) でも、こっちも定義したい いったいどうしたら…
  21. 21. そこで newtype newtype Product a = Product { getProduct :: a } deriving (Eq,Ord,Read,Show,Bounded) instance Num a => Monoid (Product a) where mempty = Product 1 Product x `mappend` Product y = Product (x * y) > getProduct $ Product 3 `mappend` Product 9 27 Sum も同じように定義されている
  22. 22. AnyとAll •Boolに対するMonoid newtype Any = Any { getAny :: Bool } deriving (Eq,Ord,Read,Show,Bounded) instance Monoid Any where mempty = Any False Any x `mappend` Any y = Any (x || y)
  23. 23. Ordering monoid •Ordering 型。値は LT, EQ, GT instance Monoid Ordering where mempty = EQ LT `mappend` _ = LT EQ `mappend` y = y GT `mappend` _ = GT 左優先。ただし左がEQの時は右。 文字列の辞書順と合わせた定義。
  24. 24. 長さ比較、 同じ時は辞書順比較 import Data.Monoid lengthCompare :: String -> String -> Ordering lengthCompare x y = (length x `compare` length y) `mappend` (x `compare` y) 便利! ほんとに便利...?
  25. 25. Maybe monoid instance Monoid a => Monoid (Maybe a) where mempty = Nothing Nothing `mappend` m = m m `mappend` Nothing = m Just m1 `mappend` Just m2 = Just (m1 `mappend` m2) 中身が Monoid の場合はこんな定義ができる
  26. 26. Maybe monoid First newtype First a = First {getFirst :: Maybe a} deriving (Eq,Ord,Read,Show) instance Monoid (First a) where mempty = First Nothing First (Just x) `mappend` _ = First (Just x) First Nothing `mappend` x = x > getFirst . mconcat . map First $ [Nothing, Just 9, Just 10] Just 9 同様に Last a も定義されている
  27. 27. 今日はここまで •今回の感想: Monoidにすると何がうれしいのかな? •次回はMonoidでの畳み込みです。 おたのしみに!
  28. 28. これも面白そう •独習 Scalaz http://goo.gl/8sXTD7 •

×