あどけない話

Internet technologies

tailをなくしたフィボナッチ数列

以下の内容は比較的どうでもいいことなので、暇な人だけ読んで下さい。

Haskell では、head と tail という関数は使うなと言われる。なぜなら、引数が空リストのときにエラーを返すからである。純粋な関数は全域関数であるべきだが、head と tail は div などと共に、この規律から逸脱している。

コーディング規約として、head や tail を禁止している組織もあるようだ。僕は、絶対に空リストでないことが保証されるところなら、まぁ、head や tail は使ってもいいかなと思う。

head や tail が、ある意味 Haskell の恥であるにも関わらず、以下のフィボナッチ数列のコードは、盛んに引用される。

fibs :: [Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

tail 不要論派の Haskeller なら、このコードは許せないだろう。しかし、tail を取り除けない人がほとんどではないか?

関数の引数として書く変数名には、@パターンが使えることは、Haskeller のほとんどが知っているだろう。実は、トップレベルの変数名にも@パターンが利用できる。だから、tail を取り除いて、以下のようなコードが書ける。

fibs,fibs' :: [Integer]
fibs@(_:fibs') = 0 : 1 : zipWith (+) fibs fibs'

分かりやすくなったのか、分かりにくくなったのか、微妙な感じではあるけれど。

追記

「二番目のコードは、パターンマッチがあるので許せない!」という方には、中野さんが書いたこのコードをどうぞ。

fibs,fibs' :: [Integer]
fibs  = 0 : fibs'
fibs' = 1 : zipWith (+) fibs fibs'