2017-12-18 7 views
4

給定某個數據類型的兩個項t1 t2,是否有某種方法可以檢查t1和t2是否以相同構造函數開始,而不在構造函數中進行窮舉或模式匹配?就像如果我喜歡的類型要麼是B,那麼我想比較Haskell中兩個項的構造函數的一般方法

checkConst (Left x) (Left y) = True 
checkConst (Right x) (Left y) = False 
... 

等實際上不這樣做,模式匹配,並在某種程度上是普遍適用於其他類型的用10層構造的順序。有沒有一個很好的方法來做到這一點?

+0

也許你可以使用[鏡頭包]中的[Pri​​sms](https://hackage.haskell.org/package/lens-4.15.4/docs/Control-Lens-Prism.html)(https: //hackage.haskell.org/package/lens-4.15.4),可能值得一試。 –

回答

6

您可能正在尋找Data.Data模塊中提供的泛型功能。如果你定義一個派生Data實例的數據類型,例如:

{-# LANGUAGE DeriveDataTypeable #-} 
import Data.Data 
data Foo = Bar1 Int 
     | Bar2 String String 
     | Bar3 Double 
     deriving (Data) 

那麼你就可以toConstr檢索一個值的構造:

> toConstr (Bar1 1) 
Bar1 
> toConstr (Bar2 "hello" "there") 
Bar2 
> 

這些都是可以Constr類型的值平等比較,這樣你就可以定義:

checkConst :: (Data g) => g -> g -> Bool 
checkConst x y = toConstr x == toConstr y 

,並得到:

> checkConst (Bar1 10) (Bar1 20) 
True 
> checkConst (Bar1 10) (Bar3 20) 
False 
> 
3

您可以使用某種中間類型,它可以唯一地區分每個構造函數並具有一個Eq實例。例如,您可以使用Int來區分每個數據構造函數,然後比較這些值。

checkConst x y = toInt x == toInt y 
    where 
    toInt (Left _) = 1 :: Int 
    toInt (Right _) = 2 

如果你的類型實現了從Data.DataData,你可以使用toConstr使用Constr爲您的中間類型。在Either的情況下,這不是必需的,因爲您可以使用isRight x == isRight y,但對於具有10個構造函數的數據類型,這將更清晰。

相關問題