>>42

 putStrLn "foo"
の場合、[Char]型の値に、[Char]->IO ()型の関数([Char]を引数に取る関数)が適用されているので型エラーは起きない。
 putStrLn "foo" ++ "bar"
の場合、関数適用は演算子の適用よりも優先度が低いので
 (putStrLn "foo") ++ "bar"
と解釈されてしまって、まぁ、直感的にもおかしい。正確にいうと、IO ()型の値と"bar"型の値にリスト連結演算子(++)::[a]->[a]->[a]が適用されているので型エラーになる。

この型エラーを回避するためには、
 putStrLn ("foo" ++ "bar")
と書いて、"foo"と"bar"に先に(++)を適用するようにすれば良い。

演算子($)は、
 f $ x = f x
と定義されている演算子で、他のどの演算子よりも優先度は低いが、関数適用よりは高い優先度を持っている。

だから、
 putStrLn $ "foo" ++ "bar"
と書くと、
 putStrLn $ ("foo" ++ "bar")
と解釈され($は++より優先度が低いから)
 putStrLn ("foo" ++ "bar")
と解釈される($の定義より)。よって、これでも問題は解決される。

この程度だと括弧()を使って優先度を操作するのと$を使うのとで大した違いはないけど、
 sortBy f5 (map f4 (groupBy f3 (filter f2 (map f1 list))))
みたいな式を書きたいときとか、括弧()の代わりに$を使うと読みやすくなる。