Pemikiran fungsional. Bagian 8

Halo, Habr! Kami kembali sedikit terlambat dari liburan Tahun Baru dengan kelanjutan seri artikel kami tentang pemrograman fungsional. Hari ini kita akan berbicara tentang memahami fungsi melalui tanda tangan dan menentukan tipe Anda sendiri untuk tanda tangan fungsi. Detail di bawah potongan!




Tidak jelas, tetapi F # memiliki dua sintaks: untuk ekspresi reguler (bermakna) dan untuk definisi tipe. Sebagai contoh:


[1;2;3] //   int list //   Some 1 //   int option //   (1,"a") //   int * string //   

Ekspresi untuk tipe memiliki sintaks khusus yang berbeda dari sintaksis ekspresi biasa. Anda mungkin telah memperhatikan banyak contoh sintaks ini saat bekerja dengan FSI (FSharp Interactive), sebagai jenis setiap ekspresi ditampilkan bersama dengan hasil pelaksanaannya.


Seperti yang Anda ketahui, F # menggunakan algoritme inferensi tipe, jadi seringkali Anda tidak perlu secara eksplisit menulis jenis dalam kode, terutama dalam fungsi. Tetapi untuk bekerja secara efektif dengan F #, Anda perlu memahami sintaks tipe sehingga Anda dapat menentukan tipe Anda sendiri, kesalahan konversi tipe debug, dan membaca tanda tangan fungsi. Pada artikel ini, saya akan fokus pada penggunaan tipe tanda tangan fungsi.


Berikut adalah beberapa contoh tanda tangan sintaksis tipe:


 //   //   let add1 x = x + 1 // int -> int let add xy = x + y // int -> int -> int let print x = printf "%A" x // 'a -> unit System.Console.ReadLine // unit -> string List.sum // 'a list -> 'a List.filter // ('a -> bool) -> 'a list -> 'a list List.map // ('a -> 'b) -> 'a list -> 'b list 

Memahami fungsi melalui tanda tangan


Seringkali, bahkan hanya dengan mempelajari tanda tangan suatu fungsi, Anda dapat mengetahui apa fungsinya. Pertimbangkan beberapa contoh dan analisis pada gilirannya.


 int -> int -> int 

Fungsi ini mengambil dua parameter int dan mengembalikan int lainnya. Kemungkinan besar, ini adalah semacam fungsi matematika, seperti penjumlahan, pengurangan, penggandaan atau eksponensial.


 int -> unit 

Fungsi ini mengambil unit int dan mengembalikan, yang berarti bahwa fungsi melakukan sesuatu yang penting sebagai efek samping. Karena tidak mengembalikan nilai yang bermanfaat, efek samping yang paling mungkin menghasilkan operasi penulisan di IO, seperti logging, menulis ke database atau yang serupa.


 unit -> string 

Fungsi ini tidak menerima apa pun, tetapi mengembalikan string , yang dapat berarti bahwa fungsi tersebut menerima string dari udara. Karena tidak ada input eksplisit, fungsi mungkin melakukan sesuatu dengan membaca (katakan dari file) atau generasi (seperti string acak).


 int -> (unit -> string) 

Fungsi ini mengambil int dan mengembalikan fungsi lain yang akan mengembalikan string ketika dipanggil. Sekali lagi, mungkin, fungsi melakukan operasi baca atau pembangkitan. Input cenderung menginisialisasi fungsi pengembalian. Misalnya, input mungkin merupakan pengidentifikasi file, dan fungsi yang dikembalikan mirip dengan readline() . Atau, input mungkin merupakan nilai awal untuk generator string acak. Kita tidak bisa mengatakan dengan pasti, tetapi kita bisa menarik beberapa kesimpulan.


 'a list -> 'a 

Fungsi menerima daftar jenis apa pun, tetapi hanya mengembalikan satu nilai dari jenis ini. Ini dapat mengindikasikan bahwa fungsi tersebut mengumpulkan daftar atau memilih salah satu elemennya. Tanda tangan serupa adalah List.sum , List.max , List.head , dll.


 ('a -> bool) -> 'a list -> 'a list 

Fungsi ini mengambil dua parameter: yang pertama adalah fungsi yang mengubah sesuatu menjadi bool (predikat), yang kedua adalah daftar. Nilai kembali adalah daftar dengan tipe yang sama. Predikat digunakan untuk menentukan apakah suatu objek memenuhi kriteria tertentu, dan apakah fungsi ini tampaknya memilih elemen dari daftar sesuai dengan predikat - benar atau salah. Setelah itu, ia mengembalikan subset dari daftar asli. Contoh fungsi dengan tanda tangan ini adalah List.filter .


 ('a -> 'b) -> 'a list -> 'b list 

Fungsi ini mengambil dua parameter: konversi dari tipe 'a to type 'b dan daftar tipe 'a . Nilai kembali adalah daftar tipe 'b . Masuk akal untuk menganggap bahwa fungsi tersebut mengambil setiap elemen dari daftar 'a , dan mengubahnya menjadi 'b , menggunakan fungsi yang diteruskan sebagai parameter pertama, dan kemudian mengembalikan daftar 'b . Memang, List.map adalah prototipe fungsi dengan tanda tangan seperti itu.


Cari metode pustaka dengan tanda tangan


Tanda tangan fungsi sangat penting dalam menemukan fungsi perpustakaan. Perpustakaan F # berisi ratusan fungsi, yang dapat membingungkan pada awalnya. Tidak seperti bahasa berorientasi objek, Anda tidak bisa sekadar "memasukkan objek" melalui titik untuk menemukan semua metode terkait. Tetapi jika Anda tahu tanda tangan dari fungsi yang diinginkan, Anda dapat dengan cepat mempersempit pencarian Anda.


Misalnya, Anda memiliki dua daftar, dan Anda ingin menemukan fungsi yang menggabungkannya menjadi satu. Tanda tangan apa yang akan dimiliki fungsi yang diinginkan? Itu harus mengambil dua daftar sebagai parameter dan mengembalikan yang ketiga, semua dari jenis yang sama:


 'a list -> 'a list -> 'a list 

Sekarang pergi ke situs dokumentasi MSDN untuk modul Daftar , dan cari fungsi yang sama. Ternyata hanya ada satu fungsi dengan tanda tangan seperti itu:


 append : 'T list -> 'T list -> 'T list 

Apa yang kamu butuhkan!


Menentukan tipe asli untuk tanda tangan fungsi


Suatu hari Anda akan ingin menentukan tipe Anda sendiri untuk fungsi yang diinginkan. Ini dapat dilakukan dengan menggunakan kata kunci "type":


 type Adder = int -> int type AdderGenerator = int -> Adder 

Di masa mendatang, Anda dapat menggunakan jenis ini untuk membatasi nilai parameter fungsi.


Misalnya, deklarasi kedua akan jatuh karena pembatasan dengan kesalahan pemeran. Jika kami menghapusnya (seperti pada pengumuman ketiga), kesalahan akan hilang.


 let a:AdderGenerator = fun x -> (fun y -> x + y) let b:AdderGenerator = fun (x:float) -> (fun y -> x + y) let c = fun (x:float) -> (fun y -> x + y) 

Menguji Tanda Tangan Fungsi Pemahaman


Apakah Anda memahami tanda tangan fungsi dengan baik? Periksa diri Anda jika Anda dapat membuat fungsi sederhana dengan tanda tangan di bawah ini. Hindari menentukan jenis secara eksplisit!


 val testA = int -> int val testB = int -> int -> int val testC = int -> (int -> int) val testD = (int -> int) -> int val testE = int -> int -> int -> int val testF = (int -> int) -> (int -> int) val testG = int -> (int -> int) -> int val testH = (int -> int -> int) -> int 

Sumber Daya Tambahan


Ada banyak tutorial untuk F #, termasuk materi untuk mereka yang datang dengan pengalaman C # atau Java. Tautan berikut mungkin berguna saat Anda masuk lebih dalam ke F #:



Beberapa cara lain untuk mulai belajar F # juga dijelaskan.


Akhirnya, komunitas F # sangat ramah pemula. Ada obrolan yang sangat aktif di Slack, didukung oleh F # Software Foundation, dengan kamar pemula yang dapat Anda gabung dengan bebas . Kami sangat menyarankan Anda melakukan ini!


Jangan lupa untuk mengunjungi situs komunitas berbahasa Rusia F # ! Jika Anda memiliki pertanyaan tentang belajar bahasa, dengan senang hati kami akan membahasnya di ruang obrolan:



Tentang penulis terjemahan


Diterjemahkan oleh @kleidemos
Perubahan terjemahan dan editorial dilakukan oleh upaya komunitas pengembang F # berbahasa Rusia . Kami juga berterima kasih kepada @schvepsss dan @shwars karena telah menyiapkan artikel ini untuk dipublikasikan.

Source: https://habr.com/ru/post/id433402/


All Articles