Sebenarnya ada tiga operator eksponensial: (^)
, (^^)
dan (**)
. ^
adalah eksponen integral non-negatif, ^^
adalah eksponensial bilangan bulat, dan eksponen **
floating-point:
(^) :: (Num a, Integral b) => a -> b -> a
(^^) :: (Fractional a, Integral b) => a -> b -> a
(**) :: Floating a => a -> a -> a
Alasannya adalah keamanan tipe: hasil operasi numerik umumnya memiliki tipe yang sama dengan argumen masukan. Tapi Anda tidak bisa menaikkan kekuatan Int
floating-point dan mendapatkan hasil tipe Int
. Dan sistem tipe mencegah Anda melakukan ini: (1::Int) ** 0.5
menghasilkan kesalahan tipe. Hal yang sama berlaku untuk (1::Int) ^^ (-1)
.
Cara lain untuk meletakkan ini: Num
tipe ditutup di bawah ^
(mereka tidak diharuskan memiliki pembalikan perkalian), Fractional
tipe ditutup di bawah ^^
, Floating
tipe ditutup di bawah **
. Karena tidak ada Fractional
contoh Int
, Anda tidak dapat menaikkannya ke pangkat negatif.
Idealnya, argumen kedua dari ^
akan dibatasi secara statis menjadi non-negatif (saat ini, 1 ^ (-2)
memunculkan pengecualian waktu proses). Tetapi tidak ada jenis bilangan asli di Prelude
.
Int
danInteger
. Untuk dapat memiliki tiga deklarasi instance tersebut, resolusi instance harus menggunakan backtracking, dan tidak ada compiler Haskell yang mengimplementasikannya.Itu tidak mendefinisikan dua operator - itu mendefinisikan tiga! Dari Laporan:
Artinya ada tiga algoritma yang berbeda, dua di antaranya memberikan hasil yang tepat (
^
dan^^
), sedangkan**
memberikan hasil perkiraan. Dengan memilih operator mana yang akan digunakan, Anda memilih algoritma mana yang akan dipanggil.sumber
^
membutuhkan argumen kedua menjadiIntegral
. Jika saya tidak salah, implementasi bisa lebih efisien jika Anda tahu Anda bekerja dengan eksponen integral. Juga, jika Anda menginginkan sesuatu seperti2 ^ (1.234)
, meskipun basis Anda adalah integral, 2, hasil Anda jelas akan menjadi pecahan. Anda memiliki lebih banyak opsi sehingga Anda dapat memiliki kontrol yang lebih ketat atas jenis apa yang masuk dan keluar dari fungsi eksponensial Anda.Sistem tipe Haskell tidak memiliki tujuan yang sama dengan sistem tipe lainnya, seperti C, Python, atau Lisp. Mengetik bebek (hampir) kebalikan dari pola pikir Haskell.
sumber
class Duck a where quack :: a -> Quack
menentukan apa yang kita harapkan dari seekor bebek, lalu setiap contoh menentukan sesuatu yang dapat berperilaku seperti bebek.Duck
.