Ich habe mit dieser einfachen Implementierung von HLists und Funktion hasInt
die True
kehrt zu experimentieren, wenn ein Int
ein Mitglied der Liste ist:GHC verwendet Catch-All-Instanz, wenn Einschränkung fehlt?
{-# LANGUAGE FlexibleInstances #-}
data HNil = HNil
deriving (Show, Read)
data HCons a b = HCons a b
deriving (Show, Read)
class HasInt a where
hasInt :: a -> Bool
instance HasInt HNil where
hasInt _ = False
instance HasInt as => HasInt (HCons a as) where
hasInt (HCons a as) = (isInt a) || (hasInt as)
class IsInt a where
isInt :: a -> Bool
instance IsInt Int where
isInt _ = True
instance {-# OVERLAPPABLE #-} IsInt a where
isInt _ = False
three = 3 :: Int
main = do
putStrLn $ "isInt three = " ++ show (isInt three) -- True
putStrLn $ "isInt True = " ++ show (isInt True) -- False
print $ hasInt $ HCons three $ HCons True HNil -- False ???
Das die erwarteten Ergebnisse nicht geben. Doch es scheint, wenn ich ändern zu arbeiten:
instance HasInt as => HasInt (HCons a as) where
zu:
instance (IsInt a, HasInt as) => HasInt (HCons a as) where
Auf der anderen Seite, ich normalerweise erwarten GHC zu beschweren, wenn ich eine Art Klassenfunktion verwenden, aber nicht enthalten die Beschränkung, und ich bekomme keine solche Anzeige in diesem Fall.
Offensichtlich hat es etwas mit der Catch-All-Instanz IsInt a
zu tun. Ich werde die Could not deduce (IsInt a) arising from a use of 'isInt'
Fehler, wenn ich die Catch-all-Instanz mit ersetzen:
instance IsInt Bool where isInt _ = False
instance IsInt HNil where isInt _ = False
Meine Frage lautet: Ist das erwartete Verhalten von GHC -, dass es leise eine Catch-all-Instanz verwenden, wenn kein expliziter ist Klassenbeschränkung eingeben?
Ich sehe keine 'Instanz IsInt Int wo isInt _ = True' hier, was mich sehr verwirrt darüber macht, wie du alles bekommst, um jemals wieder wahr zu werden. – amalloy
Ja - ich habe diese Linie verpasst. Frage aktualisiert – ErikR
Dies ist einer der Gründe dafür, dass überlappende Instanzen so schrecklich sind. Wenn Sie eine Instanz weglassen, wird alles kompiliert und alles wird falsch sein. – dfeuer