テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

Applicativeの調査

Applicative, 今までも散々使ってきていますが, ちゃんと知りたいと思います. Applicativeのメソッドについて一つ一つ調べていくかと思いましたが, 以下のリンクがまともなので, もはや, Applicativeそのものについて書くことはなさそうです.

  1. Applicativeのススメ
  2. 本物のプログラマはHaskellを使う

1は「アプリカティブスタイルを使ってコードを簡潔に書こう」ということを言っています. 布教ブログです.
2は, Applicativeのメソッドについて説明しています. なぜ「アプリカティブ」と言われるのか. その所以は「コンテナに包まれた値に対して関数を適用(apply)するところにある」と書いてあります. Functor由来の<$や, Applicativeで導入された<*, *>についても使い方を説明しています. また, Applicativeにおける

(<|>) :: f a -> f a -> f a
An associative binary operation

についても説明しています. <|>は, MonadPlusのmplusや, Monoidのmappendに相当するもの, だそうです. これはHaskellのドキュメントを探しても出てこなかった情報だったので助かりました. もう少しちゃんと調べると, Typeclassopediaによると, Appilcativeは, Monoid lawも満たさなければ「ならない」そうです.


Applicativeについてはこれ以上特に, それ自体について調査することはないのですが, 上記2の中で一箇所, 「なんでやー」な式がありましたのでそれを紐解きます. それは以下の式です.

> (*) <$> pure 11 <$> print "string" *> pure 11
"string"
11

直感的に, 何でやと感じます. 型を紐解いていきましょう.

左からpure 11まで適用すると,

(Num a) => a -> a -> a -- (*)
(Num a, Applicative f) => f a -> f (a -> a) -- <$>によって
f (a -> a) -- pure 11を適用して

という変形をします.

次に, <$>を適用するのですが, (<$>) :: (a -> b) -> f a -> f bであるため, f (a -> a)は関数a -> bでなければいけないことになります. はっ・・・関数はApplicativeじゃなイカ!?

そう信じてさらに変形します.

r -> (a -> a) <$> ...
(Applicative g) => g r -> g (a -> a) ...
IO (a -> a) *> pure 11 -- print "string"の型がIO Stringであるためgが確定

最後に, *>によって, 「IOに包まれた関数a->aが捨てられて」「最後のpure 11実行される」というロジックで, "string"が出力されて, 11が返っているのではないかと思います. ちなみに, 式の型は, 当然ですが,

*Main Control.Applicative Control.Monad Text.Parsec> :t (*) <$> pure 11 <$> print "s" *> pure 11
(*) <$> pure 11 <$> print "s" *> pure 11 :: Num b => IO b

です. 以上のロジックに誤りがあったら教えてください.

以上, Applicativeについて記事を紹介して, その中にあった疑問点について紐解いてみました. こんなくだらないことでも頭を使うものですね. こういうのが一瞬で分かるようになりたいです.

広告を非表示にする