fugafuga.write

日々のログ

すごいH本 part75

Zipリスト

ZipList という型があり、これは Applicative のインスタンスである。

instance Applicative ZipList where
    pure x = ZipList (repeat x)
    ZipList fs <*> ZipList xs = ZipList (zipWith (\f x -> f x) fs xs)

<*> は1つ目の関数を1つ目の値に、2つめの関数を2つ目の値に、... と適用する。 zipWith の仕様上短い方のリストに合わせた結果となる。

pure は、引数をとってそれを無限に繰り返すリストを返す。 この定義なら pure f <*> xsfmap f xs が等しい。という法則を満たす。

仮に pure x = ZipList [x] だった場合、 pure (*2) <*> ZipList [1,5,10] の結果は ZipList [2] になってしまう。

2つの有限リストを zip した結果の長さは短い方の長さになるため。 一方、無限リストと有限リストを zip したときの結果のリストの長さは、 有限リストの長さとなる。

ZipList a 型は Show インスタンスをサポートしていないので、 getZipList を使って生リストを取り出す必要がある。

*Main Control.Applicative> getZipList $ (+) <$> ZipList [1,2,3] <*> ZipList [100,100,100]
[101,102,103]
*Main Control.Applicative> getZipList $ (+) <$> ZipList [1,2,3] <*> ZipList [100,100..]
[101,102,103]
*Main Control.Applicative> getZipList $ max <$> ZipList [1,2,3,4,5,3] <*> ZipList [5,3,1,2]
[5,3,3,4]
*Main Control.Applicative> getZipList $ (,,) <$> ZipList "dog" <*> ZipList "cat" <*> ZipList "rat"
[('d','c','r'),('o','a','a'),('g','t','t')]

(,,)\x y z -> (x,y,z) と同じ。

zipWith 以外にも zipWith3zipWith7 までの関数がある。

所感

pure の定義の発想が自分では到底思いつかないようなものだった。自分で書いていけるか不安になった。

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

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

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