プログラミングHaskellなどを読んで、小さなコードは頭では分かるようになったのですが、大きなコードを読んだり自分で設計する際に、どのように関数の適用や合成などをイメージしたり図として表したらいいか分からず悩んでおります。
具体的には、f(x,y,z) = z*(x+y) という関数が表現したい場合、
sample.hs
(*) :: Num a => a->a->a
(+) :: Num a => a->a->a
f1 x y z = z * (x + y)
f2 x y = (*) $ (+) x y
f3 x = (*) . (+) x
のf1〜f3ような関数の書き方があると思います。また、次のような書き方は意図しない結果になっているのですが、
sample.h
g1 = (*) (+)
-- :: (Num a, Num (a -> a -> a)) => (a -> a -> a) -> a -> a -> a
g2 x = (*) $ (+) x
-- :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
g3 = (*) . (+)
-- No instance for (Num (a0 -> a0))
-- arising from a use of `*'
これらの違いを考えるために、関数を何かイメージしたいと思っています。もちろん、型の情報や式を追えば明らかなのですが、もしイメージで理解できればわかりやすくなるのかなと勝手ながら期待しています。
そこで、普段みなさんはどのようにイメージしているのか、もし良いイメージの仕方や表記方法があれば教えてください。それは慣れの問題で、本物のHaskellerにはイメージなんか必要ないというのであればそれでも構いません。(慣れるようがんばります)
参考文献は論文でも英語でも構いません。できれば、無料でアクセスできる方が助かります。