Angenommen, dass ich einige einfache algebraische Daten (im Wesentlichen enums) und einen anderen Typ, welche diese Aufzählungen als Felder hat.Haskell: Gibt es eine Möglichkeit, einen algebraischen Datentyp zu "mappen"?
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)
Angesichts einer Liste von Objekten, möchte ich testen, dass die Attribute alle unterschiedlich sind. Dazu habe ich folgende Funktionen
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 ]
(sort
von Data.List
verwenden) Dies funktioniert, aber ist nicht zufrieden stellend, weil ich jedes Feld geben musste (Farbe, Breite, Höhe) manuell. In meinem eigentlichen Code gibt es mehr Felder! Gibt es eine Möglichkeit von ‚Mapping‘ die Funktion
\field -> allDifferent $ map field objects
über die Felder eines algebraischen Datentypen wie Object
? Ich möchte Object
als eine Liste der Felder behandeln (etwas, das in zB Javascript leicht sein würde), aber diese Felder haben verschiedene Arten ...
Man könnte Schrott-your-Boilerplate verwenden. Für diesen einfachen Fall bin ich mir nicht sicher, dass es viel besser ist. – chi
Sie könnten etwas ohne Generika einbeziehen: 'uniqueAttributes objects = und [go color, go width, go height] wobei go :: (Ord a) => (Objekt -> a) -> Bool; go f = allDifferent (map f objects) ' –