LoginSignup
2
2

More than 5 years have passed since last update.

アプリカティヴとしての(->)とApplicative Styleの意味

Last updated at Posted at 2013-12-08

Applicative Styleで試してみる

(->)アプリカティヴに定義された<*>の中身は

(<*>) f g = \x -> f x (g x)

だということを意識しながら、典型的なApplicative Styleの場合:

f <$> g <*> h

がどんな函数を産みだすのかを(文系情弱なので)愚直に一歩一歩確認してみる。まず(<$>) f gは忠実に (<*>) (pure f) gとして、\x -> pure f x (g x) になるが、(pure f)は引数を無視してfを返す函数((->)アプリカティヴのpurefの実質を変えずに引数の項数だけを形式的に増やす作用だ)なので、\x -> f (g x)になる。これはもちろん(<$>)(.)と等価なことと平仄が合っていてf.gにほかならないが、このラムダ形式のまま次に進む:

f <$> g <*> h =

(\x -> f (g x)) <*> h

で、次に<*>を適用してやると:

f <$> g <*> h =

(\x -> f (g x)) <*> h =

\y -> (\x -> f ( g x )) y (h y)

ここで(\x -> f (g x)) yの部分はまさにyに対するラムダ式の無名函数の適用なのでそうしてやれば:

f <$> g <*> h =

(\x -> f (g x)) <*> h =

\y -> (\x -> f ( g x )) y (h y) =

\y -> f (g y) (h y)

おお。これはわかりやすい! これはつまり:

f <$> g <*> h $ x =

f (g x) (h x)

ということだ。引数に g を作用させたものと 引数に h を作用させたものとを f に引き渡すような函数が構成された、というわけなんだな。hがなければ、引数にgを作用させたものをfに引き渡すだけだから、函数合成 f.g になるのはもちろんだ。だからこれは函数合成を一般化した形式を提供していることになる。もちろん f はApplicativeな適用先(g ,h, …)と少なくとも同じだけの項数を持った函数である必要がある。

f <$> g <*> h <*> i $ x =

f (g x) (h x) (i x)

で、たとえばf = \ x y z -> [x, y, z]とかにすると、この函数は引数xを取って[g x, h x, i x]を返してくれるものになるわけだ。つまり、ある同じ引数を同時に多数の函数に引き渡して、そのそれぞれの結果を加工してまとめ上げる、という用途に使えるんだな(おお、なにやらモナドの気配がしてきたような……)。

しかし、そう考えると(->)アプリカティヴ・ファンクターの<*>の定義とpureの定義は実に巧妙に噛み合ってることになる。凄い。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2