誰かがHaskellの優れたコーディング標準へのリンクを提供できますか? this と this は見つかりましたが、包括的ではありません。言うまでもなく、HaskellWikiには、「注意してクラスを使用する」、「シンボリックインフィックス識別子の定義はライブラリの作成者のみに任せる」などの「gem」が含まれています。
本当に難しい質問です。あなたの答えが何か良いものになることを願っています。一方、これは私が初心者のコードで見つけた間違いやその他の迷惑なもののカタログです。 Kornel Kisielewiczが指摘しているCal Techスタイルのページと一部重複しています。私のアドバイスのいくつかは、HaskellWikiの「宝石」のように曖昧で役に立たないものですが、少なくともそれがより良いアドバイスであることを願っています:-)
80列に収まるようにコードをフォーマットします。 (上級ユーザーは87または88を好むかもしれませんが、それを超えるのはプッシュです。)
let
バインディングとwhere
句は相互に再帰的な定義のネストを作成することを忘れないでくださいnot a sequence定義。
where
句を活用します。特に、すでにスコープ内にある関数パラメーターを表示する機能(ナイスな漠然としたアドバイス)を活用してください。 Haskellを実際に操作している場合、コードにはwhere
- bindingsよりも多くのlet
- bindingsが必要です。 let
- bindingsが多すぎることは、再構築されていないMLプログラマーまたはLISPプログラマーの兆候です。
括弧の重複を避けてください。余分な括弧が特に攻撃的であるいくつかの場所は
if
式の条件の周り(再構築されていないCプログラマーとしてあなたをブランド化する)
それ自体が中置演算子の引数である関数アプリケーションの周り(関数アプリケーションは、あらゆる中置演算子よりも強くバインドされます。この事実は、私たちの恐竜がAPLを持っていたのとほぼ同じ方法で、すべてのHaskellerの脳に焼き付けられるはずです右から左へのスキャンルールが組み込まれています。
中置演算子の周りにスペースを入れます。タプルリテラルの各コンマの後にスペースを入れます。
引数が括弧で囲まれている場合でも、関数とその引数の間にはスペースを入れてください。
$
演算子を慎重に使用して、かっこを減らします。 $
とインフィックス.
の密接な関係に注意してください:
f $ g $ h x == (f . g . h) x == f . g . h $ x
組み込みのMaybe
およびEither
型を見落とさないでください。
決して書きませんif <expression> then True else False
;正しいフレーズは単に<expression>
です。
パターンマッチングを使用できる場合は、head
またはtail
を使用しないでください。
Infixドット演算子で関数の合成を見落とさないでください。
改行は慎重に使用してください。改行すると読みやすくなりますが、トレードオフがあります。エディターは一度に40〜50行しか表示しない場合があります。大きな関数を一度に読んで理解する必要がある場合は、改行を多用しないでください。
ほとんどの場合、--
コメントよりも行末まで実行される{- ... -}
コメントを優先します。中かっこで囲まれたコメントは、大きなヘッダーに適している場合があります。
各トップレベル関数に明示的な型シグニチャーを与えます。
可能な場合は、--
行、=
記号、さらには隣接する行にある括弧とコンマを揃えます。
私はGHCセントラルによって影響を受けているため、エクスポートされた識別子にはcamelCase
を使用し、ローカルwhere
- boundまたはlet
にはアンダースコア付きのshort_name
を使用することをお勧めしますバインド変数。
私の経験則のいくつかの良いルール:
Maybe (Maybe a) -> Maybe a
が必要な場合、特にjoin
がそれを行います。replicate :: Int -> a -> [a]
_のような関数の場合、各引数の型だけから、各引数の機能は明らかです。isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
のように、同じタイプの複数の引数を取る関数の場合、引数の命名/ドキュメント化がより重要です。where
句ではなく、モジュールのスコープ。Zip3
_、_zipWith3
_、_Zip4
_、_zipWith4
_などの関数のバンドルは非常に魅力的です。代わりにApplicative
スタイルでZipList
sを使用してください。あなたはおそらく本当にそのような機能を本当に必要としないでしょう。Functor
などの型クラスのインスタンスを導出するのに役立ちます(型をFunctor
のインスタンスにする正しい方法は1つだけです)。concat :: [[a]] -> [a]
_をプログラムし、join :: Monad m => m (m a) -> m a
のように一般化できることに注意してください。 join
をプログラミングするとき、誤ってリストを逆にすることができ、concat
で実行できることはほとんどないため、join
をプログラミングするときにエラーが発生する余地は少なくなります。readFile
は、ファイルが読み取られた時点では実際にはファイルの内容を読み取りません。Applicative
がZipList
のように動作した場合、それは非常に混乱する/悪いことでした。これを見てみることをお勧めします スタイルチェッカー 。
私は次のようなことを行うことで、可能な限りポイントフリースタイルのコンポジションとして機能を整理しようとしています。
func = boo . boppity . bippity . snd
where boo = ...
boppity = ...
bippity = ...
ネストされた括弧や長い括弧で囲まれた式を回避するためだけに($)を使用するのが好きです
...私はもう少し自分の中にいると思った
Haskellコードスタイルのほぼすべての側面をカバーする優れたマークダウンファイルを見つけました。チートシートとして使用できます。あなたはそれをここで見つけることができます: link