[解決済み] Haskellのガードとif-then-elseとcaseの比較
質問
リストのn番目の要素を見つける3つの関数があります。
nthElement :: [a] -> Int -> Maybe a
nthElement [] a = Nothing
nthElement (x:xs) a | a <= 0 = Nothing
| a == 1 = Just x
| a > 1 = nthElement xs (a-1)
nthElementIf :: [a] -> Int -> Maybe a
nthElementIf [] a = Nothing
nthElementIf (x:xs) a = if a <= 1
then if a <= 0
then Nothing
else Just x -- a == 1
else nthElementIf xs (a-1)
nthElementCases :: [a] -> Int -> Maybe a
nthElementCases [] a = Nothing
nthElementCases (x:xs) a = case a <= 0 of
True -> Nothing
False -> case a == 1 of
True -> Just x
False -> nthElementCases xs (a-1)
私の意見では、最初の関数が最も簡潔であるため、最良の実装だと思います。しかし、他の2つの実装について、それらが望ましいとするようなことはあるのでしょうか?また、ひいては、ガード、if-then-else文、ケースを使うかどうか、どのように選択するのでしょうか?
どのように解決するのか?
技術的な観点からは、3つのバージョンはすべて同等です。
とはいえ、スタイルに関する私の経験則では、英語のように読むことができれば(read
|
を "when"のようにします。
| otherwise
を "others"として、そして
=
を "is" または "be" として使用する場合)、おそらく何か正しいことをしているのでしょう。
if..then..else
は
1つのバイナリ条件
がある場合、または1つの決断が必要な場合に使用します。ネストされた
if..then..else
-式はHaskellでは非常に珍しく、ガードはほとんどの場合、代わりに使用されるべきです。
let absOfN =
if n < 0 -- Single binary expression
then -n
else n
すべての
if..then..else
式は関数のトップレベルにある場合、ガードで置き換えることができ、これは一般的に好ましいことです。
abs n
| n < 0 = -n
| otherwise = n
case..of
は
複数のコードパス
で、すべてのコードパスが
構造体
によって導かれ、すべてのコードパスはパターンマッチによって導かれます。でマッチすることはめったにありません。
True
と
False
.
case mapping of
Constant v -> const v
Function f -> map f
警備員の補足
case..of
の式で、値によって複雑な判断をする必要がある場合という意味です。
まず
は入力の構造に応じて判断を行い、そして
次に
は構造の中の値に対して判断を行う。
handle ExitSuccess = return ()
handle (ExitFailure code)
| code < 0 = putStrLn . ("internal error " ++) . show . abs $ code
| otherwise = putStrLn . ("user error " ++) . show $ code
ちなみに。
スタイルのヒントとして、常に
=
の後、あるいは
|
の後にあるものは
=
/
|
は1行では長すぎるか、他の理由でより多くの行を使用します。
-- NO!
nthElement (x:xs) a | a <= 0 = Nothing
| a == 1 = Just x
| a > 1 = nthElement xs (a-1)
-- Much more compact! Look at those spaces we didn't waste!
nthElement (x:xs) a
| a <= 0 = Nothing
| a == 1 = Just x
| otherwise = nthElement xs (a-1)
関連
-
[解決済み] Haskell Preludeの'const'は何のためにあるのか?
-
[解決済み] SQLのSELECTでIF...THENを実行するにはどうすればよいですか?
-
[解決済み] NGIf else "の使い方を教えてください。
-
[解決済み] Project Eulerとの速度比較。CとPythonとErlangとHaskellの比較
-
[解決済み] AngularJS テンプレートにおける if else ステートメント
-
[解決済み] RustのtraitとHaskellのtypeclassの違いは何ですか?
-
[解決済み] 制約条件付き特殊化
-
[解決済み】Haskellの入門編
-
[解決済み] Haskellの関数合成(.)と関数応用($)イディオム:正しい使い方
-
[解決済み] HaskellとF#の主な違いは何ですか?[クローズド]
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Haskell Preludeの'const'は何のためにあるのか?
-
[解決済み] haskellにおけるdrop関数 - リスト内包を用いた実装
-
[解決済み] Haskellで大規模設計?[クローズド]
-
[解決済み] Haskellのリストを参照する際の「@」記号の意味は?
-
[解決済み] GHCはなぜこんなに大きいのか/大きいのか?
-
[解決済み] Haskellのマルチコアプログラミングはどうなっているのか?
-
[解決済み] リーダーモナドの目的は何ですか?
-
[解決済み] Haskellの関数合成(.)と関数応用($)イディオム:正しい使い方
-
[解決済み] レコードの単一フィールドを割り当て、残りのフィールドはコピーするための省略記法?
-
[解決済み] Haskellはガベージコレクタを必要としますか?