6

レコード構文を使用したデータ型の例を次に示します。

data VmInfo = VmInfo {infoVid   :: String
                     ,infoIndex :: Int
                     ,infoPid   :: Int
                     ,infoExe   :: String
                     } deriving (Show)

および (vmInfo :: String -> VmInfo) 関数は、vm 名を文字列として指定すると、上記のデータ構造を生成して返します。

VmInfo データ型の個々の部分を抽出する 2 つの方法を見ることができます。

(VmInfo vid _ _ _) <- vmInfo vm

これは単なるパターンマッチです。と ...

vid <- infoVid <$> vmInfo vm

レコード構文コンパイラ生成関数の使用。

質問は簡単です: 好ましい方法はどれですか?

タイピングの量は同じなので、スピードと正確さ/ベストプラクティスを探しています。

パターン マッチングの方が速いと思いますが、レコード構文のポイントは何ですか?

ありがとう。

4

1 に答える 1

8

これらは意味的に同等ではありません。

最初の例を見てみましょう:

(VmInfo vid _ _ _) <- vmInfo vm

これにより、バインディング操作でパターンマッチングが実行されます。これには2つの結果があります。vmInfo vm1つ目は、アクションの結果のコンストラクターが評価されることです。これは、のvmInfoような行で終了した場合return undefined、評価によってスローされる例外undefinedは、後で使用するのではなく、このパターンマッチで発生することを意味しvidます。2つ目は、パターンマッチが反論された場合(パターンマッチが値と一致しない場合)、モナドのfailインスタンスがパターンマッチエラーテキストで呼び出されることです。この場合、これは不可能ですが、バインド内のコンストラクターとパターンマッチングを行う場合は一般的に可能です。

次に、次の例に進みます。

vid <- infoVid <$> vmInfo vm

の定義により<$>、これはアクションによって返される値(効果ではない)で完全に怠惰になります。vmInfoで終了した場合、の値を使用する何かを実行するまでreturn undefined、評価から例外を取得することはありません。さらに、例外をスローする機能があれば、最良の場合を使用するまで例外は発生しません。undefinedvidinfoVoidvid

興味深いことに、これらの違いは、モナディックバインドの範囲にのみ存在します。vmInfo純粋でvidletまたは式内で名前をバインドしている場合where、それらは同一のコードを生成します。

その場合、どちらを使用するかは完全にあなた次第です。どちらも慣用的なHaskellです。人々は一般的に、彼らが働いている文脈でより良く見える方を選びます。

アクセサ関数を使用する主な理由は、レコードに非常に多くのフィールドがあり、パターンマッチが非常に大きい場合の簡潔さです。また、これらは実際の関数であるため、タイプが適合する高階関数に渡すことができます。パターン一致を別個の構成として渡すことはできません。

于 2012-04-24T04:22:51.170 に答える