2

ハムレットの$case式は非常に役立つように思われますが、各フィールドのパターン マッチング (一意の名前) を除いて、複数のコンストラクターを持つレコード タイプとどのように一致するのかわかりません。データ型があるとします。

 data A = A1 { v1,v2,v3 :: Int }
        | A2 { g :: Double}

A1私のテンプレートでは、値とは異なる値をレンダリングしたいと考えていA2ます。私は簡単にできると思うでしょう、

 $case myA
    $of a@(A1 {})
      <p>This is an A1: #{show $ v1 a}
    $of a@(A2 {})
      <p>This is an A2: #{show $ g a}

@残念ながら、このスニペットは構文エラーでコンパイルに失敗し、構文がサポートされていないことを示唆しています。を削除するとa@、別の構文エラーが発生します。今回は、レコード ブレース表記もサポートされていないことを示唆しています。

最後に、必死になって、一度試すことができます。

 $case myA
    $of A1 _ _ _
      ...

しかし残念なことに、これでもコンパイルされません (_ の定義が矛盾しています)。したがって、唯一の選択肢は、

 $case myA
    $of A1 v1 v2 v3
      ...

この種の順序ベースのパターン マッチングは、特にすべてのフィールドに名前を付ける必要がある場合、大きなデータ型では非常に面倒です。

それで、私はここで何が欠けていますか?ハムレットのケース分析は、実際にそう見えるほど限定的ですか? ADT のコンストラクターと照合する (および後でフィールドを参照する) 推奨される方法は何ですか? 私がこの種のマッチングをしたいという事実は、私が Doing It Wrong(TM) をしている兆候ですか?

4

1 に答える 1

2

ハムレットの処理を追跡できます。

答えは、公開されていないモジュール Text.Hamlet.Parse にあります。

controlOf = do
    _   <- try $ string "$of"
    pat <- many1 $ try $ spaces >> ident
    _   <- spaceTabs
    eol
    return $ LineOf pat

where
  ident = Ident <$> many1 (alphaNum <|> char '_' <|> char '\'')

そのため、1 つ以上のシーケンス (スペースの後に (識別子またはワイルドカード) が続く) のみが受け入れられます。

ここから延長できます。

乾杯!

于 2012-11-06T16:11:06.597 に答える