コードを短く書くことと読みやすく書くことは違う

module Z where

import Data.Char
data Foo = Alpha | Beta | Gamma | Delta | Eta | ... | Omega
         deriving (Show,Eq,Enum,Bounded)

parse internals x = head $ (if all isLower $ take 1 x
                            then [External i | i <- [minBound..maxBound], map toLower (show i) == map toLower x] ++
                                 [Internal y | y <- internals, map toLower y == map toLower x])
                            else []) ++ [MakeIt x]

data Lib = External Foo
         | Internal String
         | MakeIt String

大幅に簡略。元コードに型無しコメント無し。

こういうゴルフコードは自慰にはいいのかもしれないですけど、他人の目には付かないところでやって欲しいですね。

Haskell を集団でうまく使うには、こういうゴルフへの逆らいがたい誘惑をいかに皆で断ち切るかに掛かっていると思います。もしくは、全員がゴルフ狂に堕ちるか。私は前者を選びたいです。他人のドヤ顔ゴルフコードを読み解きあうのは時間の無駄。

追記: ええっ、何がいけないのかわからないですって?

そういう人は、他人と一緒に働く仕事には向いていません。さようなら。

関数の型がない

parse :: [String] -> String -> Lib と型さえ書いていれば parse っていう名前だから、なんとなく文字列から Lib を作りだすんだと判る。その時点でコードを読む必要が無い人はこのコードを解読する作業から解放されます。てか、Lib の定義は前に書けよ。

関数のコメントがない

小文字から始まる場合は Foo のコンストラクタもしくは internals からマッチを探し出すよ、マッチが見つからないか大文字の場合は MakeIt x になるよ、と書いてくれれば、その時点で機能は理解できるから、機能が間違っているから変更したい、とか、コードにバグがあるようだ、という時以外は、このコードを解読する作業から開放されます。

そんなのコードと同じ内容のコメント書いていられるかって?じゃあ、パターンマッチ使って、もっと上のコメントに近い読みやすいコードにしろよ。長くなってもいいからさぁ。

Enum や Bounded を使って華麗に文字列からコンストラクタへの変換を行っているが型が無いので何してるか判らねえ

この華麗な方式自体は大変結構ですけど、[minBound..maxBound] だけでは何を列挙しているのかわからない。いや目を皿のようにしてようく眺めれば判りますよ、そりゃ。でも、([MinBound..maxBound] :: [Foo]) とか書いてありさえすれば、私のドライアイも悪化しないですむわけですよ!

最初の文字が小文字、ならそう書いてよ!

all isLower $ take 1 x を日本語にしてみてください。「最初の一文字からなるリストを作りそのリストの全ての要素が小文字。」意味わからないです。最初の文字が小文字 ならば isLower $ head x の方が自然じゃないですか? それだと x が "" の時動かないじゃないか?それは別のケースにすりゃいいじゃない! 何でもかんでも短く書いてやろうってなるからこんな式になる。そして、「Haskell だとこんなに簡潔に書けます」。「こんなに簡潔で意味不明に書くことも出来ます」の間違いじゃないですか?

Incomprehensible list comprehension

これが Haskell のコードスタイルですと言われればしょうがないけど、なんでもリストにし過ぎですよ。いろいろな所から探してくる結果の一番初めに見つかったやつだけ欲しいってのを遅延評価で書けば head $ リストの式 になるのは判りますよ。短く書けるし。でもこの例ではもう私は理解できないですよ。せめて上に挙げたような関数のコメントがあれば、そういう心積もりで読みますからいいんですけど。

長いけどさあ、こう書いた方が他の人に親切じゃないかいなあ。

まあ型とコメントがちゃんとしてればコードは元のままでいいけどね。

module Z where

import Data.Char
data Foo = Alpha | Beta | Gamma | Delta | Eta | ... | Omega
         deriving (Show,Eq,Enum,Bounded)
data Lib = External Foo
         | Internal String
         | MakeIt String

-- 小文字から始まる場合、 Foo もしくは internals からマッチを探す、
-- それ以外の場合やマッチが無ければは MakeIt x になるよ
parse :: [String] -> String -> Lib

parse internals "" = MakeIt "" -- というかエラーにすべきだよ多分

parse internals x | isLower $ head x = 
  head $ [External i | i <- ([minBound..maxBound] :: [Foo]), match show x i] ++
         [Internal y | y <- internals, match x y] ++
         [MakeIt x]
    where
        match x y = map toLower x == map toLower y

parse internals x = MakeIt x