Pointfree / ((->) r)モナド
http://www.haskell.org/haskellwiki/Pointfree を読んだ。その中で、
> pl \ x -> x * x join (*)
が何故動くのかで悩んだ。そもそもjoinはMonadに対する関数(join :: (Monad m) => m (m a) -> m a)である。その前には"The @pl (point-less) plugin is rather infamous for using the (-> a) monad to obtain concise code."と書かれており、joinのmが b -> という型(引数型?)、つまり(b -> b -> a) -> (b -> a)だと考えれば話が通りそうである。実際、調べてみると
*Main> :info (->) data (->) a b -- Defined in GHC.Prim instance Monad ((->) r) -- Defined in Control.Monad.Instances instance Functor ((->) r) -- Defined in Control.Monad.Instances
となっており、Control.Monad.Instancesでモナドとして定義されていることがわかった。
まずjoinの定義を確認しておく。
http://haskell.org/ghc/docs/latest/html/libraries/base/src/Control-Monad.html#join
join :: (Monad m) => m (m a) -> m a join x = x >>= id
次に((->) r)モナドの定義を見てみた。
http://haskell.org/ghc/docs/latest/html/libraries/base/src/Control-Monad-Instances.html
instance Monad ((->) r) where return = const f >>= k = \ r -> k (f r) r
なるほど、fに引数rを与えて評価した結果がkに渡されて、加えてkにもr自体が渡されている。returnがconstなのも興味深い。引き回されているrが引数として渡されるのだから、これを読み捨ててしまえばいいわけだ。
最後にjoin (*) xを簡約してみれば、確かにx * xになっていることが確認できた。
((*) >>= id) x (\ r -> id ((*) r) r) x ((*) x) x x * x