【发布时间】:2017-05-22 05:40:26
【问题描述】:
假设我有一些简单的代数数据(本质上是枚举)和另一种将这些枚举作为字段的类型。
data Color = Red | Green | Blue deriving (Eq, Show, Enum, Ord)
data Width = Thin | Normal | Fat deriving (Eq, Show, Enum, Ord)
data Height = Short | Medium | Tall deriving (Eq, Show, Enum, Ord)
data Object = Object { color :: Colour
, width :: Width
, height :: Height } deriving (Show)
给定一个对象列表,我想测试这些属性是否都是不同的。为此,我有以下功能(使用来自Data.List 的sort)
allDifferent = comparePairwise . sort
where comparePairwise xs = and $ zipWith (/=) xs (drop 1 xs)
uniqueAttributes :: [Object] -> Bool
uniqueAttributes objects = all [ allDifferent $ map color objects
, allDifferent $ map width objects
, allDifferent $ map height objects ]
这行得通,但相当不满意,因为我必须手动输入每个字段(颜色、宽度、高度)。在我的实际代码中,还有更多字段!有没有办法“映射”函数
\field -> allDifferent $ map field objects
像Object 这样的代数数据类型的字段?我想将Object 视为其字段的列表(在例如 javascript 中很容易实现),但这些字段具有不同的类型...
【问题讨论】:
-
可以使用废品你的样板。对于这个简单的案例,我不确定这是否更好。
-
你可以在没有泛型的情况下考虑它:
uniqueAttributes objects = and [go color, go width, go height] where go :: (Ord a) => (Object -> a) -> Bool; go f = allDifferent (map f objects)
标签: haskell records algebraic-data-types