Ich habe einen algebraischen Datentyp mit einigen Konstruktoren, die vergleichbare Werte enthalten, und einigen Konstruktoren, die dies nicht tun. Ich habe einige Vergleichsfunktionen geschrieben, die wie die Standard (==)
y (/=)
Operatoren, sondern geben Nothing
für Vergleiche, die keinen Sinn ergeben:
data Variant = IntValue Int
| FloatValue Float
| NoValue
equal :: Variant -> Variant -> Maybe Bool
equal (IntValue a) (IntValue b) = Just (a == b)
equal (FloatValue a) (FloatValue b) = Just (a == b)
equal _ _ = Nothing
unequal :: Variant -> Variant -> Maybe Bool
unequal (IntValue a) (IntValue b) = Just (a /= b)
unequal (FloatValue a) (FloatValue b) = Just (a /= b)
unequal _ _ = Nothing
Das funktioniert, aber die Wiederholungen sind unhandlich - zumal ich eigentlich mehr Variant
Konstruktoren und weitere Vergleichsfunktionen.
Ich dachte, ich könnte Faktor aus der Wiederholung in eine Hilfsfunktion, die auf die Vergleichsfunktion parametrisiert ist:
helper :: (Eq a) => (a -> a -> Bool) -> Variant -> Variant -> Maybe Bool
helper f (IntValue a) (IntValue b) = Just (f a b)
helper f (FloatValue a) (FloatValue b) = Just (f a b)
helper _ _ _ = Nothing
equal' :: Variant -> Variant -> Maybe Bool
equal' = helper (==)
unequal' :: Variant -> Variant -> Maybe Bool
unequal' = helper (/=)
aber das funktioniert nicht, weil die Typvariable a
kann sich offenbar nicht an beide Int
y Float
gleichzeitig in der Definition von helper
; GHC bindet es an Float
und beschwert sich dann über eine Typfehlanpassung in der Zeile, die die IntValue
.
Eine Funktion wie (==)
ist polymorph, wenn sie direkt verwendet wird; gibt es eine Möglichkeit, sie an eine andere Funktion zu übergeben und sie polymorph zu halten?