December 3, 2012

Haskell: ชนิดของฟังก์ชัน

ถ้าลองใช้ :t ตรวจชนิดของฟังก์ชันดูบ้าง จะเห็นแบบนี้


ส่วนที่บอก type จะอยู่หลังเครื่องหมาย => เช่นเคย โดยฝั่งซ้ายของ -> จะเป็นตัวแปรที่รับเข้ามาในฟังก์ชัน ส่วนฝั่งขวาคือผลลัพท์จากฟังก์ชัน นั่นหมายความว่าฟังก์ชัน fromIntegral รับตัวแปรใน type class Integral แล้วได้ผลลัพท์เป็น type class Num

การเขียนฟังก์ชันนั้น เช่นเดียวกับการประกาศค่าคงที่ คือใช้ let พร้อมชื่อฟังก์ชันและตัวแปร เช่น




ทีนี้ลองดูฟังก์ชันของ 2 ตัวแปรกันบ้าง


สิ่งที่แตกต่างไปจากภาษา imperative และถือได้ว่าเป็นจุดเด่นของภาษาแบบ functional เลยคือ แทนที่ type ของฟังก์ชัน 2 ตัวแปรจะใช้ช่องว่างคั่นตัวแปร (type น่าจะอยู่ในรูป a a -> a) แต่ระหว่างตัวแปรกลับใช้สัญลักษณ์ -> เช่นเดียวกับการบอกผลลัพท์ที่ได้จากฟังก์ชัน

เราอาจลองแบ่งกลุ่มเพื่อความกระจ่างใน type ว่ามันคือ a -> (a -> a) ซึ่งหมายความว่า ฟังก์ชันนี้เป็นฟังก์ชันที่รับตัวแปร 1 ตัว แล้วให้ผลลัพท์เป็นฟังก์ชันที่รับตัวแปร 1 ตัวแล้วคืนค่าออกมาก็ย่อมได้

นั่นหมายความว่า ฟังก์ชัน 2 ตัวแปร แท้จริงแล้วคือฟังก์ชัน 1 ตัวแปร 2 ชั้น เราจึงสามารถเรียกฟังก์ชันแบบนี้


ได้เช่นกัน นี่เป็นเหตุผลว่าทำไม Haskell ถึงไม่ใช้วงเล็บล้อมรอบตัวแปร เราเรียกเทคนิคการทำให้ฟังก์ชันหลายตัวแปรกลายร่างเป็นฟังก์ชันตัวแปรเดียวซ้อนๆ กันเช่นนี้ว่า currying และเรียกฟังก์ชันที่รับตัวแปรเข้าไปแล้วบ้างแต่ยังไม่ครบว่า partial application ครับ



อนึ่ง เราสามารถเขียนการหารเก็บเศษข้างบนเป็นแบบนี้ 123456789 `mod` 1009 และถ้าเราต้องการเอาวงเล็บล้อมรอบ `mod` 1009 ด้านหลัง มันจะกลายเป็นฟังก์ชันที่รับตัวแปรไปแล้ว 1 ตัว และต้องการอีก 1 ที่ต้องทำต่อคือย้ายมันไปไว้ข้างหน้าเท่านั้นเอง


ซึ่งสามารถจับมาประกาศเป็นฟังก์ชันได้ว่า


หรือยิ่งไปกว่านั้น




กลับไปดูฟังก์ชัน half ที่เขียนไว้ตอนต้นอีกที เราลองเขียนมันใหม่เป็น


จะเห็นว่าไม่เพียงแต่ฟังก์ชันเท่านั้น ที่เราสามารถนำวงเล็บไปล้อมรอบได้ แต่นี่ยังรวมไปถึง operator ด้วย นอกจากนี้



นั่นหมายความว่า operator เหล่านั้นก็ถือเป็นฟังก์ชันเช่นเดียวกันนั่นเอง

No comments:

Post a Comment