让我们考虑一个数据类型有许多构造函数:“模式匹配”代数数据类型的构造函数
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