各コンビネータに対応する関数
type | Combinator | Prelude | Monad | Applicative |
---|---|---|---|---|
a -> a | I x = x | id | ask | |
a -> b -> a | K x y = x | const | return | pure |
(a -> b) -> (c -> a) -> c -> b | B x y z = x (y z) | (.) | liftM | |
(a -> b -> c) -> b -> a -> c | C x y z = x z y | flip | ||
(a -> a) -> a | Y x = x (Y x) | fix | ||
(a -> b -> c) -> (a -> b) -> a -> c | S x y z = x z (y z) | ?? | ap | <*> |
Sコンビネータの型は(a -> b -> c) -> (a -> b) -> a -> c
これで調べると、Readerモナドのap、Applicativeの<*>等が対応するようだ。
あまり深く考えずに Reader a を a -> と読み替えると、関数の型は以下のようになります。
関数 型 等価な関数 ap (a->b->c) -> (a->b) -> a -> c <*> つまり Reader モナドは引数隠蔽モナドだと思えばいいわけですね。本当は第一引数があるのだけれども、あたかもそれが引数に存在しないかのように記述できると。
http://d.hatena.ne.jp/rst76/20091006/1254835633
*1 -> (a -> b) -> (a -> c)
http://practical-scheme.net/chaton/haskell-ja/a/2009/11/02
というわけで,これが S コンビネータ
あと、Monad のインスタンスである(Reader r)に対応する(>>=)が CSかも。
Applicativeについて
どうやらMonadやArrowのようなフレームワーク(?)の一種らしい
Applicativeの使い方が少し見えてきました。
http://d.hatena.ne.jp/Otter_O/20080301/1204363038
mapでこうやることが:
map (+ 1) [1, 2, 3] = [2, 3, 4]
Applicativeだとこうできる:
pure (+1) <*> [1, 2, 3] = [2, 3, 4]
いくつのリストを対象に関数を適用するかで、map = 1, zipWith = 2, zipWith3 = 3,...と使う関数を変えていかなくてはならないのですが、Applicativeであれば、pureと<*>だけで何個リストがあっても大丈夫...これはきれいです。
そもそも、PreludeとControl.MonadとControl.ArrowとControl.Applicativeはそれぞれ導入の時期もずれていて、十分に整理されているわけではありません。
http://practical-scheme.net/chaton/haskell-ja/a/2009/10/30
追記
次のエントリーに求めていたものズバリがあった。
Sコンビネータいろいろ
http://d.hatena.ne.jp/rst76/20091006/1254840491
モナドとコンビネータ論理のコラボ!とか喜んでたら、既に先達が。
PreludeにSかWを入れる提案があったが却下されてたらしい。
Joe Fasel argued for the inclusion of S or W in the prelude
http://www.haskell.org/pipermail/haskell-cafe/2005-February/009117.html
on the grounds that a complete combinator base would be "neat".
But the majority of the Haskell committee didn't buy that.