私は、Haskellの$演算子や.演算子がきらいです。だって読む順番が逆だから。
数学ではそう書く?数学で函数合成なんてだらだら続けないでしょう?でもプログラミングだと必要な処理は書き下します。
Project Eulerの問題4を例にします。
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 * 99.
Find the largest palindrome made from the product of two 3-digit numbers.
2つの3桁の数の積から作られるパリンドロームの最も大きなものを見つけなさい。
Haskellで書くと、以下のようになります。
ans = (maximum . map (read :: String -> Int) . filter isPalindrome . map show) products where isPalindrome s = s == reverse s products = [m * n | m<-[100..999], n<-[100..999]] main = putStrLn $ show ans
英語の順としては合ってますね。でも私は日本人だからお尻から読むことになります。
で、Unixのパイプのような演算子を作りました。
module MyBase where (|$) :: a -> (a -> b) -> b (|$) x f = f x infixl 0 |$
|$演算子は左項の引数を右項の引数函数で処理する左結合演算子です。
|を使いたかったのですが、これはガードなので使えません。似たような機能の$と混ぜて |$としました。
これを使うと、先ほどのコードは以下のように書けます。
import MyBase ans = products |$ map show |$ filter isPalindrome |$ map (read :: String -> Int) |$ maximum where isPalindrome s = s == reverse s products = [m * n | m <- [100..999], n <- [m..999]] main = putStrLn $ show ans
「積のリストを、文字にして、パリンドロームだけ残し、数字に戻して、最大を見つける。」日本語の順番通りに書けます。画期的に読みやすくなりました。これって日本人だけ?