関数

8.4 ポイントフリースタイル


むむむ…、なかなか難しい概念ですね。
頭の中を整理すると、要は


関数を式(値)ではなく、式(値)から独立した関数で定義すること


をポイント(値)フリー(独立)スタイルというのかな。
たしかにこれまで関数を定義(関数に変数を束縛)する時、式で定義していました。
たとえば

myMax :: (Int, Int) -> Int
myMax (x, x) = 0
myMax (x, y) = if x > y then x else y


では、「0」や「if x > y then x else y」はいずれも式です。

takeLast n ss = reverse $ take n $ reverse ss


もそうですね。「reverse $ take n $ reverse ss」は式です。
だけど、これを次のように書きます。

takeLast n = reverse . take n . reverse


引数(n)は一つ使ってますけど、右辺は関数です。
ちょっと疑問が…。これって次のようにも書けるのかな?

  • tail.hs
main = do cs <- getContents
          putStr $ lastNLines 10 cs

lastNLines n cs = unlines $ takeLast n $ lines cs

-- takeLast n ss = reverse $ take n $ reverse ss
-- takeLast n = reverse . take n . reverse
takeLast n = reverse $ take n $ reverse


それっ!

% ghc -W -o tail tail.hs 

tail.hs:8:32:
    Couldn't match expected type `[a]'
           against inferred type `[a1] -> [a1]'
    In the second argument of `($)', namely `reverse'
    In the second argument of `($)', namely `take n $ reverse'
    In the expression: reverse $ take n $ reverse


あれれ、だめですねぇ。
reverse関数の型は[a1]->[a1]なのに、[a]で使われているとな。
なるほど、「$」は単に括弧と同じで式をまとめているだけだからね。
「$」に対する理解が深まりました。