Saya mencoba memahami apa yang dilakukan operator titik dalam kode Haskell ini:
sumEuler = sum . (map euler) . mkList
Seluruh kode sumber ada di bawah.
Pemahaman saya
Operator titik mengambil dua fungsi sum
dan hasil dari map euler
dan hasil mkList
sebagai masukan.
Tapi, sum
bukankah sebuah fungsi itu adalah argumen dari fungsinya, bukan? Jadi apa yang terjadi disini?
Juga, apa yang (map euler)
dilakukannya?
Kode
mkList :: Int -> [Int]
mkList n = [1..n-1]
euler :: Int -> Int
euler n = length (filter (relprime n) (mkList n))
sumEuler :: Int -> Int
sumEuler = sum . (map euler) . mkList
sumber
f (g x)
=(f . g) x
"?) Atau sesuatu yang lain?==
jika menginginkan Haskell standar yang valid.Itu. operator menyusun fungsi. Sebagai contoh,
a . b
Dimana a dan b adalah fungsi adalah fungsi baru yang berjalan b pada argumen, maka hasil tersebut. Kode Anda
sumEuler = sum . (map euler) . mkList
persis sama dengan:
sumEuler myArgument = sum (map euler (mkList myArgument))
tapi semoga lebih mudah dibaca. Alasan adanya parens di sekitar map euler adalah karena memperjelas bahwa ada 3 fungsi yang disusun: sum , map euler dan mkList - map euler adalah fungsi tunggal.
sumber
sum
adalah fungsi dalam Haskell Prelude, bukan argumen untuksumEuler
. Ini memiliki tipeNum a => [a] -> a
Operator komposisi fungsi
.
memiliki tipeJadi kita punya
euler :: Int -> Int map :: (a -> b ) -> [a ] -> [b ] (map euler) :: [Int] -> [Int] mkList :: Int -> [Int] (map euler) . mkList :: Int -> [Int] sum :: Num a => [a ] -> a sum . (map euler) . mkList :: Int -> Int
Perhatikan bahwa
Int
ini memang sebuah instance dari kelasNum
tipe.sumber
Itu. operator digunakan untuk komposisi fungsi. Sama seperti matematika, jika Anda memiliki fungsi f (x) dan g (x) f. g menjadi f (g (x)).
peta adalah fungsi built-in yang menerapkan fungsi ke daftar. Dengan meletakkan fungsi di dalam tanda kurung, fungsi tersebut diperlakukan sebagai argumen. Istilah untuk ini adalah kari . Anda harus mencarinya.
Apa yang dilakukan adalah bahwa ia mengambil fungsi dengan mengatakan dua argumen, itu menerapkan argumen euler. (map euler) kan? dan hasilnya adalah fungsi baru, yang hanya membutuhkan satu argumen.
jumlah . (peta euler). mkList pada dasarnya adalah cara yang bagus untuk menggabungkan semua itu. Saya harus mengatakan, Haskell saya agak berkarat tapi mungkin Anda bisa menggabungkan fungsi terakhir itu sendiri?
sumber
Jawaban singkat
Kode yang setara tanpa titik, itu adil
sumEuler = \x -> sum ((map euler) (mkList x))
atau tanpa lambda
sumEuler x = sum ((map euler) (mkList x))
karena titik (.) menunjukkan komposisi fungsi.
Jawaban yang lebih panjang
Pertama, mari kita sederhanakan penerapan parsial
euler
untukmap
:map_euler = map euler sumEuler = sum . map_euler . mkList
Sekarang kita hanya punya titik-titiknya. Apa yang ditunjukkan oleh titik-titik ini?
Dari sumber :
Dengan demikian
(.)
adalah operator yang compose .Menyusun
Dalam matematika, kita bisa menulis komposisi fungsi, f (x) dan g (x), yaitu, f (g (x)), sebagai
yang bisa dibaca "f tersusun dengan g".
Jadi di Haskell, f ∘ g, atau f yang terdiri dari g, bisa ditulis:
f . g
Komposisi bersifat asosiatif, yang berarti bahwa f (g (h (x))), yang ditulis dengan operator komposisi, dapat menghilangkan tanda kurung tanpa ambiguitas.
Artinya, karena (f ∘ g) ∘ h ekivalen dengan f ∘ (g ∘ h), kita cukup menulis f ∘ g ∘ h.
Berputar kembali
Kembali ke penyederhanaan kami sebelumnya, ini:
sumEuler = sum . map_euler . mkList
hanya berarti itu
sumEuler
adalah komposisi yang belum diterapkan dari fungsi-fungsi tersebut:sumEuler = \x -> sum (map_euler (mkList x))
sumber
Operator titik menerapkan fungsi di kiri (
sum
) ke output fungsi di kanan. Dalam kasus Anda, Anda merangkai beberapa fungsi bersama - Anda meneruskan hasilmkList
ke(map euler)
, lalu meneruskan hasilnya kesum
. Situs ini memiliki pengantar yang bagus untuk beberapa konsep.sumber