2012-06-05 75 views
7

我有這樣的數據類型構造模式匹配的Haskell

data Struct val = Empty | Exec1 val 
         | Exec2 val 

和兩個僞功能

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" 

第二個是工作正常,但第一個導致錯誤:「在模式解析錯誤: EXEC」。你可以解釋爲什麼我不能在構造函數上這樣匹配: apply(exec struct)= ...?

當我在我的數據類型中有多個構造函數並且必須分別將它們全部單獨匹配時,會導致很多樣板代碼。

回答

3

爲什麼?因爲你只能匹配構造函數,並且exec是一種新的變量。其中一個原因是,例如以下:

data Struct2 = Empty | Exec1 String 
         | Exec2 Int 

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

人怎麼會知道其中Exec1Exec2你匹配?您無法在此處應用功能,因爲無法確定struct的實際類型。

如果你想減少模式匹配,有多種方式,使用case,在不同的data地執行(如@Karolis建議)和輔助功能,更高級別的結構更復雜的類型。但這是一個無盡的話題。

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" 
19

在一般情況下,如果你有幾個構造函數共享數據,那麼它通常最好的數據聲明重構爲類似

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" 

,你仍然可以模式匹配到特定的執行類型

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

在這種情況下重新使用預定義的'Maybe'類型可能是個好主意。 – dflemstr

1

在您的特定情況下,你可以做到以下幾點:

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

這不會很好地擴展到更復雜的結果雖然。

0
apply Empty = "matched empty" 
apply (Exec1 _) = notEmpty 
apply (Exec2 _) = notEmpty 

notEmpty = "matched Exec1 or Exec2"