Apa perbedaan antara titik (.)
dan tanda dolar ($)
?
Seperti yang saya pahami, keduanya adalah gula sintaksis karena tidak perlu menggunakan tanda kurung.
sumber
Apa perbedaan antara titik (.)
dan tanda dolar ($)
?
Seperti yang saya pahami, keduanya adalah gula sintaksis karena tidak perlu menggunakan tanda kurung.
The $
operator adalah untuk menghindari tanda kurung. Apa pun yang muncul setelah itu akan diutamakan daripada apa pun yang datang sebelumnya.
Misalnya, Anda memiliki garis yang berbunyi:
putStrLn (show (1 + 1))
Jika Anda ingin menghilangkan tanda kurung itu, salah satu dari baris berikut ini juga akan melakukan hal yang sama:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
Tujuan utama .
operator bukan untuk menghindari tanda kurung, tetapi untuk fungsi rantai. Ini memungkinkan Anda mengikat output apa pun yang muncul di sebelah kanan dengan input apa pun yang muncul di sebelah kiri. Ini biasanya juga menghasilkan lebih sedikit kurung, tetapi bekerja secara berbeda.
Kembali ke contoh yang sama:
putStrLn (show (1 + 1))
(1 + 1)
tidak memiliki input, dan karena itu tidak dapat digunakan dengan .
operator.show
dapat mengambil Int
dan mengembalikan a String
.putStrLn
dapat mengambil String
dan mengembalikan sebuah IO ()
.Anda dapat rantai show
untuk putStrLn
seperti ini:
(putStrLn . show) (1 + 1)
Jika terlalu banyak tanda kurung untuk keinginan Anda, singkirkan mereka dengan $
operator:
putStrLn . show $ 1 + 1
putStrLn . show . (+1) $ 1
akan setara. Anda benar karena sebagian besar (semua?) Operator infiks adalah fungsi.map ($3)
. Maksudku, aku lebih sering menggunakannya$
untuk menghindari tanda kurung, tapi bukan hanya itu yang ada di sana.map ($3)
adalah fungsi dari tipeNum a => [(a->b)] -> [b]
. Dibutuhkan daftar fungsi mengambil nomor, berlaku 3 untuk semuanya dan mengumpulkan hasilnya.Mereka memiliki tipe dan definisi yang berbeda:
($)
dimaksudkan untuk menggantikan aplikasi fungsi normal tetapi pada prioritas yang berbeda untuk membantu menghindari tanda kurung.(.)
adalah untuk menyusun dua fungsi bersama untuk membuat fungsi baru.Dalam beberapa kasus mereka dapat dipertukarkan, tetapi ini tidak benar secara umum. Contoh khas di mana mereka berada adalah:
==>
Dengan kata lain dalam rantai
$
s, semua kecuali yang terakhir dapat digantikan oleh.
sumber
x
suatu fungsi? Bisakah Anda gunakan.
sebagai yang terakhir?x
dalam konteks ini, maka ya - tapi kemudian yang "final" akan berlaku untuk sesuatu selainx
. Jika Anda tidak mendaftarx
, maka tidak ada bedanya denganx
menjadi nilai.Juga mencatat bahwa
($)
adalah fungsi identitas khusus untuk jenis fungsi . Fungsi identitas terlihat seperti ini:Sementara
($)
terlihat seperti ini:Perhatikan bahwa saya sengaja menambahkan tanda kurung tambahan pada tanda tangan jenis.
Penggunaan
($)
biasanya dapat dihilangkan dengan menambahkan tanda kurung (kecuali operator digunakan dalam bagian). Misalnya:f $ g x
menjadif (g x)
.Penggunaan
(.)
sering sedikit lebih sulit untuk diganti; mereka biasanya membutuhkan lambda atau pengenalan parameter fungsi eksplisit. Sebagai contoh:menjadi
menjadi
Semoga ini membantu!
sumber
($)
memungkinkan fungsi dirantai bersama tanpa menambahkan tanda kurung untuk mengontrol urutan evaluasi:Operator penulisan
(.)
membuat fungsi baru tanpa menentukan argumen:Contoh di atas bisa dibilang ilustratif, tetapi tidak benar-benar menunjukkan kenyamanan menggunakan komposisi. Berikut analogi lainnya:
Jika kita hanya menggunakan yang ketiga sekali, kita dapat menghindari memberi nama dengan menggunakan lambda:
Akhirnya, komposisi memungkinkan kita menghindari lambda:
sumber
Versi singkat dan manis:
($)
memanggil fungsi yang merupakan argumen sebelah kiri pada nilai yang merupakan argumen sebelah kanannya.(.)
menyusun fungsi yang merupakan argumen sebelah kiri pada fungsi yang merupakan argumen kanannya.sumber
Salah satu aplikasi yang berguna dan perlu waktu bagi saya untuk mencari tahu dari deskripsi yang sangat singkat di belajar Anda haskell : Sejak:
dan tanda kurung sisi kanan ekspresi yang mengandung operator infiks mengubahnya menjadi fungsi awalan, orang dapat menulis
($ 3) (4+)
analog dengan(++", world") "hello"
.Mengapa ada orang yang melakukan hal ini? Untuk daftar fungsi, misalnya. Kedua:
dan:
lebih pendek dari
map (\x -> x ++ ", world") ...
ataumap (\f -> f 3) ...
. Jelas, varian yang terakhir akan lebih mudah dibaca oleh kebanyakan orang.sumber
$3
ruang. Jika Template Haskell diaktifkan, ini akan diuraikan sebagai sambungan, sedangkan$ 3
selalu berarti apa yang Anda katakan. Secara umum tampaknya ada kecenderungan di Haskell untuk "mencuri" sintaks dengan bersikeras bahwa operator tertentu memiliki ruang di sekitar mereka untuk diperlakukan seperti itu.Mereka bukan gula sintaksis karena tidak perlu menggunakan tanda kurung - mereka adalah fungsi, - diinfiksasi, sehingga kita dapat menyebutnya operator.
Tulis,,
(.)
dan kapan menggunakannya.(.)
adalah fungsi menulis. Begitusama dengan membangun fungsi yang meneruskan hasil dari argumen yang diteruskan
g
kef
.Gunakan
(.)
saat Anda tidak memiliki argumen yang tersedia untuk diteruskan ke fungsi yang ingin Anda buat.Asosiatif yang tepat berlaku
($)
,, dan kapan menggunakannya($)
adalah fungsi berlaku asosiatif-kanan dengan diutamakan mengikat rendah. Jadi itu hanya menghitung hal-hal di sebelah kanannya terlebih dahulu. Jadi,sama dengan ini, secara prosedural (yang penting karena Haskell dievaluasi dengan malas, itu akan mulai dievaluasi
f
terlebih dahulu):atau lebih ringkas:
Gunakan
($)
ketika Anda memiliki semua variabel untuk dievaluasi sebelum Anda menerapkan fungsi sebelumnya pada hasilnya.Kita dapat melihat ini dengan membaca sumber untuk setiap fungsi.
Baca Sumbernya
Inilah sumber untuk
(.)
:Dan inilah sumber untuk
($)
:Kesimpulan
Gunakan komposisi ketika Anda tidak perlu segera mengevaluasi fungsi. Mungkin Anda ingin meneruskan fungsi yang dihasilkan dari komposisi ke fungsi lain.
Gunakan aplikasi saat Anda memasok semua argumen untuk evaluasi penuh.
Jadi untuk contoh kita, secara semantik lebih disukai untuk melakukannya
ketika kita memiliki
x
(atau lebih tepatnya,g
argumen), dan lakukan:ketika kita tidak melakukannya.
sumber
... atau Anda dapat menghindari
.
dan$
konstruksi dengan menggunakan pipelining :Itu setelah Anda menambahkan fungsi helper:
sumber
$
operator Haskell sebenarnya bekerja lebih seperti F #<|
daripada itu|>
, biasanya dalam haskell Anda akan menulis fungsi di atas seperti ini:third xs = head $ tail $ tail $ xs
atau mungkin bahkan sepertithird = head . tail . tail
, yang dalam sintaks gaya F # akan menjadi seperti ini:let third = List.head << List.tail << List.tail
$
sudah tersedia, dan itu disebut&
hackage.haskell.org/package/base-4.8.0.0/docs/...Cara yang bagus untuk belajar lebih banyak tentang apa saja (fungsi apa saja) adalah dengan mengingat bahwa semuanya adalah fungsi! Mantra umum itu membantu, tetapi dalam kasus-kasus tertentu seperti operator, ada baiknya mengingat trik kecil ini:
dan
Ingatlah untuk menggunakan
:t
secara bebas, dan bungkus operator Anda()
!sumber
Aturan saya sederhana (saya juga pemula):
.
jika Anda ingin melewatkan parameter (panggil fungsi), dan$
jika belum ada parameter (susun fungsi)Itu adalah
tapi tidak pernah:
sumber
Saya pikir contoh singkat dari mana Anda akan menggunakan
.
dan tidak$
akan membantu memperjelas hal-hal.Perhatikan bahwa
times6
ini adalah fungsi yang dibuat dari komposisi fungsi.sumber
Semua jawaban lain cukup bagus. Tetapi ada detail kegunaan yang penting tentang bagaimana ghc memperlakukan $, bahwa pemeriksa tipe ghc memungkinkan untuk instatiarion dengan peringkat yang lebih tinggi / jenis terkuantifikasi. Jika Anda melihat jenis
$ id
misalnya Anda akan menemukan itu akan mengambil fungsi yang argumennya sendiri merupakan fungsi polimorfik. Hal-hal kecil seperti itu tidak diberi fleksibilitas yang sama dengan operator gangguan yang setara. (Ini benar-benar membuat saya bertanya-tanya apakah $! Layak mendapatkan perawatan yang sama atau tidak)sumber