4

Haskell関数を定義する古典的な方法は

f1 :: String -> Int
f1 ('-' : cs) -> f1 cs + 1
f1 _ = 0

すべての行に関数名を書くのはちょっと不満です。現在、私は通常、パターンガード拡張機能を使用して次のように記述し、より読みやすく、変更しやすいと考えています。

f2 :: String -> Int
f2 s
  | '-' : cs <- s = f2 cs + 1
  | otherwise = 0

2番目の例は、より読みやすく、変更可能で、エレガントだと思いますか?生成されたコードはどうですか?(まだ脱糖された出力を見る時間はありません、ごめんなさい!)。短所は何ですか?私が見るのは拡張機能の使用法だけです。

4

2 に答える 2

8

まあ、あなたはいつでも次のように書くことができます:

f3 :: String -> Int
f3 s = case s of
           ('-' : cs) -> f3 cs + 1
           _          -> 0

これは、バージョンと同じことを意味しf1ます。関数の名前が長いか読みにくい場合、多くのパターンと照合したい場合、これはおそらく改善になるでしょう。ここでの例では、従来の構文を使用します。

あなたのバージョン自体には何の問題もありませんが、f2誰もが慣れ親しんでいると想定するほど一般的ではない構文GHC拡張の使用は少し軽薄に思えます. 個人的なコードの場合は大したことではありませんが、case他の人が読んでいると思われるものはすべてこの表現に固執します。

于 2012-09-13T13:55:04.827 に答える
6

あなたの場合に示されているように、何かにパターンマッチングを行う場合は、関数名を書く方が好きです。私はそれがより読みやすいと思います。

関数の引数にいくつかの条件がある場合はガードを使用することを好みます。これはif else、最初のパターンに従う場合に使用する必要がある、を回避するのに役立ちます。

だからあなたの質問に答えるために

Do you think that second example is more readable, modifiable and elegant?

いいえ、私はシンプルで読みやすい最初のものを好みます。しかし、多かれ少なかれそれはあなたの個人的な好みに依存します。

What about generated code?

生成されたコードに違いはないと思います。どちらも単なるパターンマッチングです。

What are cons? 

パターンガードは、letなどをよりクリーンに使用する代わりに、パターンマッチングに役立ちます。

addLookup env var1 var2
   | Just val1 <- lookup env var1
   , Just val2 <- lookup env var2
   = val1 + val2

もちろん、欠点は拡張機能を使用する必要があり、Haskell98ではありません(これはあまり欠点とは見なされない可能性があります)

一方、関数の引数の簡単なパターンマッチングでは、最初の方法を使用します。これは単純で読みやすい方法です。

于 2012-09-13T13:58:55.097 に答える