In dieser Antwort versuche ich, die historischen Gründe für die inkonsistente Schnittstelle zu betrachten. Zusammenfassung: Es scheint, dass Brent während des Betriebs einige generische Funktionen verwendet hat, um die Formulierung von QuickCheck-Eigenschaften zu erleichtern.
Warum ist splitPlaces
generisch?
Es sieht so aus, als würde Brent den Typ splitPlaces
verallgemeinern, um die Einführung von QuickCheck-Eigenschaften für diese Funktion zu erleichtern. Die QuickCheck-Eigenschaften verwenden newtype-Wrapper, um die Testfallgenerierung zu steuern, und mit der Integral a
-Einschränkung könnte splitPlaces
diesen Wrapper des neuen Typs für die arithmetischen Operationen durchsuchen. Siehe auch:
aber hier ist eine der Eigenschaften über splitPlaces
:
prop_splitPlaces_preserve :: [NonNegative Integer] -> [Elt] -> Bool
prop_splitPlaces_preserve ps l = concat (splitPlaces ps' l) == genericTake (sum ps') l
where ps' = map unNN ps
Beachten Sie, dass Quick Check automatisch die Liste ps
erzeugt, die durch map unNN ps
umgewandelt wird, bevor splitPlaces
geleitet wird. Die unNN
Funktion entfernt die NonNegative
Wrapper, so splitPlaces
muss nicht mit der NonNegative
Wrapper selbst beschäftigen. Es erhält jedoch ein Argument vom Typ [Integer]
anstelle von [Int]
, sodass es im numerischen Typ immer noch generisch sein muss.
Was ist der Sinn der Verwendung von [NonNegative Integer]
anstelle von [NonNegative Int]
?
Ich vermute, dass die Eigenschaft für [Int]
wegen arithmetischer Überläufe falsch ist, wenn die Summe berechnet wird. Die Eigenschaft könnte sogar durch QuickCheck verfälscht werden, da die Arbitrary [NonNegative Integer]
Instanz schließlich an arbitrarySizedBoundedIntegral
delegiert wird, die sehr große Werte generieren kann.
Ich denke, dass die Verwendung von [NonNegative Integer]
statt dieses Problem auf zwei Arten umgeht:
- Mit
Integer
kann keine Überläufe auftreten.
- Die
Arbitrary Integer
Instanz delegiert an arbitrarySizedIntegral
, die nur kleine Werte generiert.
Also ich denke, dass der Grund dafür, dass beliebigen Integral-Typ ist, dass die Quick Check Eigenschaft würde für Int
scheitert aber gelingt für Integer
.
Warum ist chunksOf
nicht generisch?
Die Eigenschaften für chunksOf
verwenden Mustervergleich, um die Wrapper des neuen Typs zu entfernen. Siehe auch:
Dies ist eine der Eigenschaften über chunksOf
:
prop_chunksOf_all_n :: Positive Int -> NonEmptyList Elt -> Bool
prop_chunksOf_all_n (Positive n) (NonEmpty l) = all ((==n) . length) (init $ chunksOf n l)
Beachten Sie, dass diese Eigenschaft auf den Argumenten übereinstimmt, die von Quick Check automatisch generiert werden und übergibt sie an chunksOf
ohne newtype-Wrapper. Für die Argumente, die zum Testen chunksOf
erforderlich sind, ist dies leicht zu tun, da die Zahlen nicht in anderen Typen verschachtelt sind. Vergleichen Sie mit prop_splitPlaces_preserve
oben, wo Konvertierung [NonNegative Integer]
zu [Integer]
oder [Int]
etwas komplizierter als nur Mustervergleich erfordert. Der Unterschied zwischen Arbitrary Int
und Arbitrary Integer
spielt hier keine Rolle, da die Eigenschaft keine Operationen beinhaltet, die einen arithmetischen Überlauf auslösen können.
Gute Frage! Aus der Sicht der Schnittstelle sehe ich keinen besonderen guten Grund - vielleicht nur eine etwas einfachere Implementierung. Könnte Standardisierung verwenden. Welcher von beiden besser ist, hängt von der Perspektive ab, es wird Unstimmigkeiten geben. – luqui