讓我們考慮一個數據類型有許多構造函數:「模式匹配」代數數據類型的構造函數
data T = Alpha Int | Beta Int | Gamma Int Int | Delta Int
我想編寫一個函數來檢查是否有相同的構造產生了兩個值:
sameK (Alpha _) (Alpha _) = True
sameK (Beta _) (Beta _) = True
sameK (Gamma _ _) (Gamma _ _) = True
sameK _ _ = False
維護sameK
沒有多少樂趣,也不容易檢查正確性。例如,當新構造函數被添加到T
時,很容易忘記更新sameK
。我省略了一行舉例:
-- it’s easy to forget:
-- sameK (Delta _) (Delta _) = True
問題是如何避免樣板sameK
?或者如何確保它檢查所有T
構造函數?
我發現的解決方法是使用單獨的數據類型的每個構造的,推導Data.Typeable
,並聲明一個普通型類,但我不喜歡這樣的解決方案,因爲它是非常少可讀和否則只是一個簡單的代數類型的工作對我來說:
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Typeable
class Tlike t where
value :: t -> t
value = id
data Alpha = Alpha Int deriving Typeable
data Beta = Beta Int deriving Typeable
data Gamma = Gamma Int Int deriving Typeable
data Delta = Delta Int deriving Typeable
instance Tlike Alpha
instance Tlike Beta
instance Tlike Gamma
instance Tlike Delta
sameK :: (Tlike t, Typeable t, Tlike t', Typeable t') => t -> t' -> Bool
sameK a b = typeOf a == typeOf b
謝謝大家回答。你所有的答案都很有用。 – sastanin 2010-04-14 08:59:03