Es gibt eigentlich drei Potenzierung Betreiber: (^)
, (^^)
und (**)
. ^
ist eine nicht negative integrale Exponentiation, ^^
eine ganzzahlige Exponentiation und **
eine Gleitkomma-Exponentiation:
(^) :: (Num a, Integral b) => a -> b -> a
(^^) :: (Fractional a, Integral b) => a -> b -> a
(**) :: Floating a => a -> a -> a
Der Grund ist die Typensicherheit: Ergebnisse numerischer Operationen haben im Allgemeinen den gleichen Typ wie die Eingabeargumente. Sie können jedoch keine Int
auf eine Gleitkomma-Potenz erhöhen und ein typisches Ergebnis erhalten Int
. Das Typsystem verhindert dies und verhindert (1::Int) ** 0.5
einen Typfehler. Das gilt auch für (1::Int) ^^ (-1)
.
Eine andere Möglichkeit, dies auszudrücken: Num
Typen werden unter geschlossen ^
(sie müssen keine multiplikative Inverse haben), Fractional
Typen werden unter geschlossen ^^
, Floating
Typen werden unter geschlossen **
. Da es keine Fractional
Instanz für gibt Int
, können Sie sie nicht auf eine negative Potenz erhöhen.
Idealerweise wäre das zweite Argument von ^
statisch darauf beschränkt, nicht negativ zu sein ( 1 ^ (-2)
löst derzeit eine Laufzeitausnahme aus). Aber es gibt keinen Typ für natürliche Zahlen in der Prelude
.
Mikhail Glushenkov
quelle
Int
als als auch istInteger
. Um diese drei Instanzdeklarationen zu erhalten, muss die Instanzauflösung Backtracking verwenden, und kein Haskell-Compiler implementiert dies.Es definiert nicht zwei Operatoren - es definiert drei! Aus dem Bericht:
Dies bedeutet, dass es drei verschiedene Algorithmen gibt, von denen zwei genaue Ergebnisse (
^
und^^
) liefern , während sie**
ungefähre Ergebnisse liefern. Durch Auswahl des zu verwendenden Operators wählen Sie den aufzurufenden Algorithmus aus.quelle
^
erfordert, dass sein zweites Argument ein istIntegral
. Wenn ich mich nicht irre, kann die Implementierung effizienter sein, wenn Sie wissen, dass Sie mit einem integralen Exponenten arbeiten. Wenn Sie so etwas wie möchten2 ^ (1.234)
, obwohl Ihre Basis ein Integral 2 ist, ist Ihr Ergebnis offensichtlich ein Bruchteil. Sie haben mehr Optionen, damit Sie genauer steuern können, welche Typen in Ihre Exponentiationsfunktion ein- und ausgehen.Das Typsystem von Haskell hat nicht das gleiche Ziel wie andere Typsysteme wie C, Python oder Lisp. Das Tippen von Enten ist (fast) das Gegenteil der Haskell-Denkweise.
quelle
class Duck a where quack :: a -> Quack
definiert, was wir von einer Ente erwarten, und dann gibt jede Instanz etwas an, das sich wie eine Ente verhalten kann.Duck
.