web-dev-qa-db-ja.com

Haskellで部分関数を回避する利点は何ですか?

HaskellのAFAIKでは、部分的な機能を回避することを強くお勧めします。これらが避けられないように見える場合(例:head)、Maybeを返します。少なくとも、Haskell wikiは 12 と言っています

パターンの用途は何ですか?

部分的に見える関数があるとしましょう。コンパイル時間をチェックするのが難しいと思われるいくつかの要件を満たすために、その引数が必要です。また、コードの他の部分を台無しにしない限り、このような引数で呼び出すのは意味がないため、関数を非準拠の引数で呼び出すことはできません。

部分的な関数を記述していてバグがあると、プログラムがクラッシュします。これは悪いので代わりに...

アドバイスに従ってMaybeを返す場合-遅かれ早かれ、このMaybeを最終的にパターンマッチングする必要があります。最終的にmain :: IO()Maybeを受け取ったときに、実用的なデータを出力したい場合、mainはどうしますか?

プログラマーが馬鹿であるというエラーを出力しますか?

ええと...私は、関数を部分的にしておけばどうなるかを正確に示しています。それを簡単に台無しにした情報が得られないことを除いて。

ここで何が欠けていますか?

4
gaazkam

ソフトウェアに不正な状態が含まれているため、部分的な機能は不良です。これらを回避する最もエレガントな解決策は、たとえば特定のプロパティを保証する値に新しいタイプを導入することにより、違法な状態を表現不可能にすることです。

ただし、Haskellの型システムは弱すぎて、「少なくとも1つの要素を含むリスト」などの特定のプロパティを表すことができません。これにより、回避策が必要になります。

  • ソフトウェアが不正な状態になった場合、すぐにクラッシュすることは賢明なことです。予期せぬ事態が発生したため、違法な状態から回復するための方法がわかりません。

  • 部分的な関数a -> bを関数に変換するa -> Maybe bそれを合計関数として書くことができます–処理したくない入力は違法ではなく、Nothingにマップするだけです。型システムは幸せです、あなたは幸せです。はい、そのモナドはプログラムの残りの部分に伝播しますが、Haskellはこれを耐えられるようにするために必要な抽象化を提供します。場合によっては、代わりにデフォルト値を返すことが理にかなっています。

最善の方法は、おそらくこの関数に対するあなたの見解に依存します。これは実際には一部の入力を無視する部分的な関数ですか?または、おそらく実行時チェックによって除外する必要があるプログラム内の違法な状態はありますか?

ハスケルのhead :: [a] -> a関数は、実行時エラーがスローされるように、空のリストを渡すことは不正であると判断した例です。これは実用的なアプローチですが、まだ有効です。しかし、それが正しい設計であったかどうかは非常に議論の余地があります。ほとんどのコードでは、Maybe値を返し、呼び出し側に決定(エラー、伝達、デフォルト)を任せるほうがよいでしょう。

4
amon