10

私はこのデータ型を持っています

data Struct val =  Empty | Exec1 val
                         | Exec2 val 

そして2つのダミー関数

apply :: Struct -> String
apply (Empty) = "matched Empty"  
apply (exec struct) = "matched Exec1 or Exec2"              

apply' :: Struct val -> String
apply' (Empty)   = "matched Empty"  
apply' (Exec1 _) = "matched Exec1"
apply' (Exec2 _) = "matched Exec2"

2 つ目は正常に動作していますが、最初のものは「パターンの解析エラー: exec」というエラーを引き起こしています。apply (exec struct) = ... のようにコンストラクターで一致できない理由を説明してください。

データ型に複数のコンストラクターがあり、それらすべてを個別にパターン マッチする必要がある場合、多くのボイラープレート コードが発生します。

4

5 に答える 5

22

一般に、データを共有するコンストラクターが複数ある場合は、通常、データ宣言を次のようにリファクタリングすることをお勧めします。

data Struct val = Empty | NonEmpty StructType val
data StructType = Exec1 | Exec2

applyこれで、このようにパターンマッチできます

apply :: Struct -> String
apply (Empty) = "matched Empty"  
apply (NonEmpty exec struct) = "matched Exec1 or Exec2"

また、特定の Exec タイプへのパターン マッチも可能です。

apply' :: Struct val -> String
apply' (Empty)   = "matched Empty"  
apply' (NonEmpty Exec1 _) = "matched Exec1"
apply' (NonEmpty Exec2 _) = "matched Exec2"
于 2012-06-05T08:27:52.787 に答える
3

「exec」は型コンストラクターではなく、パターン マッチングでのみ使用できます。

あなたができることは

data Struct val =  Empty | Exec Int val

apply :: Struct -> String
apply (Empty) = "matched Empty"  
apply (Exec _ _) = "matched Exec1 or Exec2"              

apply' :: Struct val -> String
apply' (Empty)   = "matched Empty"  
apply' (Exec 1 _) = "matched Exec1"
apply' (Exec 2 _) = "matched Exec2"
于 2012-06-05T08:14:42.820 に答える
3

なんで?コンストラクターのみを一致させることができ、exec一種の新しい変数であるためです。この理由の 1 つは、たとえば次のようなものです。

data Struct2 =  Empty | Exec1 String
                      | Exec2 Int

apply :: Struct2 -> String
apply Empty = "matched Empty"  
apply (exec struct) = ??

と のどちらが一致しているかを誰がどのように知る必要がExec1ありますか? Exec2の実際の型をstruct特定できなかったため、ここで関数を適用できませんでした。

パターン マッチングを減らしたい場合は、caseさまざまなdata実装 (@Karolis が提案するような) やヘルパー関数を使用することから、より複雑な型のより高いレベルの構造体まで、さまざまな方法があります。しかし、それは終わりのないトピックです。

于 2012-06-05T08:23:42.493 に答える
2

特定のケースでは、次のことができます。

apply :: Struct -> String
apply Empty = "matched Empty"  
apply _     = "matched Exec1 or Exec2"

ただし、これはより複雑な結果にうまくスケーリングされません。

于 2012-06-05T13:16:29.337 に答える
0
apply Empty = "matched empty"
apply (Exec1 _) = notEmpty
apply (Exec2 _) = notEmpty

notEmpty  = "matched Exec1 or Exec2"
于 2012-06-05T15:38:00.093 に答える