3回目のHaskell

奇跡の3回目!!いやよく挫折せずに続いているなとちょっと感心しています。難易度に押しつぶされるかと思ったけどそうでもないな。むしろ面白くなってきたところ。この調子でチャレンジし続けたいです。
今日のお題は"area.c"です。多角形の面積を求めるプログラムです。例によって説明は割愛します(ぉぃ
多少慣れてきたので割とスムーズに書けちゃいました。

main = print ( area [(1,1),(3,2),(2,4),(0,2)] )

area :: [(Double,Double)] -> Double
area []     = 0
area (n:ns) = subarea (n:ns) n / 2.0

subarea :: [(Double,Double)] -> (Double,Double) -> Double
subarea [] _         = 0
subarea [n] t        = cross n t
subarea (n:m:ms) t = cross n m + subarea (m:ms) t

cross :: (Double,Double) -> (Double,Double) -> Double
cross (x1,y1) (x2,y2) = x1 * y2 - x2 * y1

ちょっと新しい文法も使ってみようと無理にタプルなんぞ使っています(^^;座標なので本当ならdataとか使って定義した方がスマートなのかもしれませんがまだ早い(?)ので遠慮しておきました(ぉ
タプルを使っているだけで前回から特に目新しい部分はありません。なので今回はもうちょっと頑張ってみました。外積の結果を全て足すのだから、まずは外積のリストを作るとかできないかな?というアプローチで頑張ってみました。その結果、ごらんの有様になりましたorz

main = print ( area [(1,1),(3,2),(2,4),(0,2)] )

area :: [(Double,Double)] -> Double
area [] = 0
area n  = (/2.0) $ sum $ map cross $ zip n $ shift n
    where shift (n:ns) = ns ++ [n]
          cross ((x1,y1),(x2,y2)) = x1 * y2 - x2 * y1

やった!直接ループを使ってないぞ!空のリストのパターンマッチングがあるので再帰っぽい形ですが再帰になってません。あくまで空のリストが渡された場合のエラー処理(?)です。無くても一応動きます。
これを書くにあたり、sumとかmapとかzipとか調べまくりました。や、ものすごく経験値がたまりました。

さて、頑張ったもののこれはHaskellらしいコードなのかな?それとも逆にかけ離れたのかな?まあ、とりあえず経験値は溜まったのでよしとします(^^;