Предположим, что у меня есть некоторые простые алгебраические данные (по существу перечисления) и другой тип, который имеет эти перечисления как поля.Haskell: есть ли способ «отображения» над алгебраическим типом данных?
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)
Учитывая список объектов, я хочу проверить, что все атрибуты различны. Для этого у меня есть следующие функции (с помощью sort
из Data.List
)
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), но эти поля имеют разные типы ...
Можно использовать лом-ваш-шаблон. Для этого простого случая я не уверен, что это намного лучше. – chi
Вы можете немного его отличить от дженериков: 'uniqueAttributes objects = и [go color, go width, go height], где go :: (Ord a) => (Object -> a) -> Bool; go f = allDifferent (объекты map f) ' –