Ci sono in realtà tre operatori di elevazione a potenza: (^)
, (^^)
e (**)
. elevamento integrante ^
è non negativo, ^^
è elevamento intero e **
è virgola mobile a potenza:
(^) :: (Num a, Integral b) => a -> b -> a
(^^) :: (Fractional a, Integral b) => a -> b -> a
(**) :: Floating a => a -> a -> a
La ragione è di tipo sicurezza: risultati delle operazioni numeriche hanno generalmente lo stesso tipo come argomento ingresso (s) . Ma non è possibile aumentare un valore di Int
in virgola mobile e ottenere un risultato di tipo Int
. E così il sistema di tipi ti impedisce di fare questo: (1::Int) ** 0.5
produce un errore di tipo. Lo stesso vale per (1::Int) ^^ (-1)
.
Un altro modo per mettere questa: Num
tipi sono chiusi rispetto ^
(non sono tenuti ad avere un inverso moltiplicativo), Fractional
tipi sono chiusi sotto ^^
, Floating
tipi sono chiusi rispetto **
. Poiché non è presente l'istanza Fractional
per Int
, non è possibile aumentarla a una potenza negativa.
Idealmente, il secondo argomento di ^
sarebbe staticamente vincolato per essere non negativo (al momento, 1^(-2)
genera un'eccezione run-time). Ma non esiste un tipo per i numeri naturali nel Prelude
.
fonte
2011-06-19 04:54:01
Non sono completamente d'accordo sul fatto che la mentalità di tipo Haskell sia l'opposto della digitazione anatra. Le classi di tipo Haskell sono molto simili alla digitazione anatra. 'classe Duck a where quack :: a -> Quack' definisce cosa ci aspettiamo da un'anatra, e quindi ogni istanza specifica qualcosa che può comportarsi come un'anatra. – augustss
@augusts Vedo da dove vieni. Ma il motto informale dietro la digitazione anatra è "se sembra un'anatra, si comporta come un'anatra, e ciarlona come un'anatra, quindi è un'anatra". In Haskell non è un'anatra a meno che non sia dichiarata un'istanza di "Anatra". –
È vero, ma è quello che mi aspetterei da Haskell. Puoi fare tutto ciò che vuoi, ma devi essere esplicito a riguardo. Non vogliamo scambiare qualcosa che non abbiamo chiesto di essere un'anatra. – augustss