「F# をまねる」をまねる

Ruby はオブジェクトが左から右に流れて行きます。

total = 0
(1..100).map{|x| x*2}.select{|x| x%6== 0}.each{|x|total+=x}
print total  # => 3366

Haskell だと右から左に流れますので左から右へ文字を書いている民族としてはやや不自然なところがあります。

> sum $ filter (\x -> x `mod` 6 == 0) $ map (*2) [1..100]
-- => 3366

kazu-yamamotoさんの「あどけない話」に「F# をまねる」と言う記事がありました。

-- 関数と引数を逆に記述する関数
infixl 0 |>
(|>) :: a -> (a -> b) -> b
a |> f = f a

-- (|>) は関数と引数を逆に記述するための関数です。
> putStrLn "Hello" 
-- => Hello

> (|>) "Hello" putStrLn 
-- => Hello

-- ()を外して |> とする
> "Hello" |> putStrLn 
-- => Hello

> [1..100] |> map (*2) |> filter (\x -> x `mod` 6 == 0) |> sum
-- => 3366

部分摘要された (map (*2))、(filter (\x -> x `mod` 6 == 0)) は一つの引数をとる関数として働きます。関数は一つの引数を受け取ると結果を次に送って、リストは関数を適用されながら左から右へ流れます。
ここで次から次に送られるのは一番最後の引数であるリストです。関数を定義するときは重要な引数は最後にしておけば何かと良いことがありそうです。

  • おまけ。結合の優先順位
-- http://zvon.org/other/haskell/Outputprelude/index.html

infixr 9  .
infixr 8  ^, ^^, **
infixl 7  *, /, `quot`, `rem`, `div`, `mod`
infixl 6  +, -
infixr 5  :
infix  4  ==, /=, <, <=, >=, >
infixr 3  &&
infixr 2  ||
infixl 1  >>, >>=
infixr 1  =<<
infixr 0  $, $!, `seq`

Debug.Trace を使う nobsun(2007/07/04 10:53:31 JST)

import Debug.Trace
 
infixr 0 .$.
(.$.) :: Show a => (a -> b) -> a -> b
f .$. x = trace (show x) f x
 
infixr 9 ...
(...) :: Show b => (b -> c) -> (a -> b) -> (a -> c)
f ... g = (f .$.) . g