fugafuga.write

日々のログ

すごいH本 part77

モノイド

Monoid は、値を2項演算子で結合できるような型を表現する。

newtype キーワード

newtype キーワードを使うと、既存の型から新たな型を作ることができる。

リストをアプリカティブファンクターにする方法は複数ある。

左辺のリストの関数と右辺のリストの値のあらゆる組み合わせのリストを作る方法。

*Main Control.Applicative> [(+1),(*100),(*5)] <*> [1,2,3]
[2,3,4,100,200,300,5,10,15]

2つのリストを綴じ合わせるように新たなリストを作る方法。 ZipListを使う。

*Main Control.Applicative> getZipList $ ZipList [(+1),(*100),(*5)] <*> ZipList [1,2,3]
[2,200,15]

ZipList データ型宣言をどう書くか考える

data ZipList a = ZipList [a]

レコード構文を使うとこうなる

data ZipList a = ZipList { getZipList :: [a] }

newtype を使うとこうなる

newtype ZipList a = ZipList { getZipList :: [a] }

ZipList は実際にこのようにnewtypeで定義されている。 data で定義されない理由は、コンストラクタに包んだりほどいたりするような処理のオーバーヘッドがかかるため。

newtype は既存の型を何かでくるんで新しい型を作るために使う。

いくつか制約もある。

  • 値コンストラクタは1種類しか作れない
  • 値コンストラクタに持てるフィールドも1種類だけ

data の場合、上記のような制約は無い。

data Profession = Fighter | Archer | Accountant
data Race = Human | Elf | Orc | Goblin
data PlayerCharacter = PlayerCharacter Race Profession

newtype で作った型に対しても data と同じように deriving で型クラスのインスタンスを導出できる。

*Main Lib> newtype CharList = CharList { getCharList :: [Char] } deriving (Eq, Show)
*Main Lib> CharList "this will be shown!"
CharList {getCharList = "this will be shown!"}
*Main Lib> CharList "benney" == CharList "benny"
False
*Main Lib> CharList "benney" == CharList "benney"
True

[Char] をとり、CharList を返す値コンストラクタとなっている。

一方、getCharList の型宣言

*Main Lib> :t getCharList
getCharList :: CharList -> [Char]

CharList をとり、[Char] を返す関数となっている。

これは、2種類の型の間の変換だと考えることができる。

newtype を使って型クラスのインスタンスを作る

タプルをFunctorのインスタンスにしたいと考える。

fmap をタプルに作用させて第一要素を変更するようにしたい。 fmap (+3) (1,1) と書いたら (4,1) になるように。

Maybe の場合、型引数が1つなので Functor のインスタンスにするのはすんなりいけるが、 (a,b) の場合、fmap が作用するのは型 a の部分だけだよーと指定するのはできない。

この制限を回避するために、タプルを newtype して2つの型引数の順番を入れ替える。

newtype Pair b a = Pair { getPair :: (a, b) }

これをインスタンスにする

instance Functor (Pair c) where
    fmap f (Pair (x, y)) = Pair (f x, y)

newtype で作った型にはパターンマッチが使える。

実行

*Main> getPair $ fmap (*100) (Pair (2, 3))
(200,3)
*Main> getPair $ fmap reverse (Pair ("london calling", 3))
("gnillac nodnol",3)

所感

モノイドの章なのにモノイドという単語が出てこなかった

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

  • 作者: MiranLipovaca
  • 出版社/メーカー: オーム社
  • 発売日: 2017/07/14
  • メディア: Kindle版
  • 購入: 4人 クリック: 9回
  • この商品を含むブログを見る