Es ist wirklich ziemlich einfach. Lassen Sie uns GHCi fragen, was die Art der isList2
ist:
∀x. x ⊢ :t isList2
isList2 :: a -> Bool
Dies ist nicht die [a]
Instanz überein (obwohl es könnte, über Vereinigung), aber es passen die a
Instanz sofort. Daher wählt die GHC a
Beispiel isList2
so kehrt False
.
Dieses Verhalten ist genau das, was IncoherentInstances
Mittel. Eigentlich ist das eine schöne Demonstration davon.
Vergnügt, wenn Sie einfach IncoherentInstances
deaktivieren, erhalten wir genau die entgegengesetzte Wirkung, und GHCi sagt jetzt das:
∀x. x ⊢ :t isList2
isList2 :: [Integer] -> Bool
Dies geschieht, weil isList2
ist ein Top-Level-Bindung nicht mit der Funktion Syntax definiert und somit der gefürchteten Monomorphie Restriktion unterliegen. Es wird also auf die Instanz spezialisiert, mit der es tatsächlich verwendet wird.
Hinzufügen NoMonomorphismRestriction
sowie das Deaktivieren IncoherentInstances
, bekommen wir diese statt:
∀x. x ⊢ :t isList2
isList2 :: IsList a => a -> Bool
∀x. x ⊢ isList2 'a'
False
∀x. x ⊢ isList2 "a"
True
∀x. x ⊢ isList2 undefined
<interactive>:19:1:
Overlapping instances for IsList a0 arising from a use of `isList2'
, das das erwartete überlappende Verhalten ist, mit der Instanz gewählt basierend auf der Verwendung und Beschwerden, wenn die Wahl nicht eindeutig ist.
In Bezug auf die Bearbeitung der Frage glaube ich nicht, dass das gewünschte Ergebnis ohne Typ Anmerkungen möglich ist.
Die erste Möglichkeit besteht darin, isList2
eine Typ-Signatur zu geben, die verhindert, dass IncoherentInstances
eine Instanz zu früh auswählt.
isList2 :: (IsList a) => a -> Bool
isList2 = isList
Sie werden wahrscheinlich das gleiche tun müssen anderswo isList
erwähnt wird (wenn auch indirekt) ohne auf ein Argument angewendet wird.
Die zweite Option ist die Zahlenliterale und deaktivieren IncoherentInstances
eindeutig zu machen.
main =
print (isList (42 :: Integer)) >>
print (isList2 (42 :: Integer)) >>
print (isList [42]) >>
print (isList2 [42])
In diesem Fall gibt es genug Informationen, eine sehr spezifische Instanz zu holen, so OverlappingInstances
seine Sache tut.
Da Ihr Programm ist inkohärent. Wirklich, was hast du * erwartet *? –
Ich erwartete, dass die Ausgabe "True True" ist, nicht "True False". Warum erwarten Sie, dass die Ausgabe "True False" ist? Warum sollte das inkohärente Programm nicht 'True True' zurückgeben? Willst du damit sagen, dass es keinen Grund für die Ausgabe gibt, und das Ergebnis ist undefiniert, und es kann manchmal "True True" zurückgeben? – Clinton
möglich Duplikat von [Wie funktioniert IncoherentInstances arbeiten?] (Http://stackoverflow.com/questions/8371499/how-does-incoherentinstances-work) –