Monday, November 27, 2006

Currying

Christopher Diggins เขาเขียนเรื่อง Typing like a Functional Programme
article นี้ช่วยเฉลยให้ผมเข้าใจเรื่อง currying ขึ้นอีกหน่อย
(เห็นศัพท์นี้บ่อย แต่ไม่ get ว่ามันคืออะไร)

ตัวอย่างที่เขาอธิบายก็คือ
function add_ints
ปกติเวลาเราเขียน imperative language เช่น java
add_ints จะเขียนแบบนี้
public int add_ints(int x, int y) { return x + y; }


ถ้าจะเขียนเป็น functional language (ocaml, haskell, ...)
เราต้อง declare type ก่อน
ซึ่ง type ของ add_ints เขียนได้ดังนี้
add_ints: int -> int -> int

อ่านได้ว่า add_ints รับ parameter ชนิด int 2 ตัว
แล้ว return ค่าเป็น int

จะเห็นว่ามันดูแปลกๆ เพราะในความคิดแบบ imperative ของเราแล้ว
มันควรจะเขียนแบบนี้มากกว่า
add_ints: (int , int) -> int
add_ints: (int -> int) -> int


ที่เป็นเช่นนี้เพราะ ใน Haskell (ขอยกตัวอย่างเฉพาะ haskell) มันพิสดารตรงที่ว่า
ถ้าเรา pass parameter แค่ตัวเดียวให้กับ add_ints version java
ผลก็คือ code จะ compile ไม่ผ่าน
แต่สำหรับกับพวก haskell แล้ว
การ pass parameter ตัวเดียวให้กับ add_ints
มันจะ return กลับมาเป็น function อีก function หนึ่งแทน
โดย function นั้นจะรับ parameter ที่เป็น int ตัวเดียว
และเมื่อเรา call function นั้นอีกทอด เราก็จะได้ผลบวกที่ต้องการ

ลองดูตัวอย่าง
add_ints :: int -> int -> int
add_ints x y = x + y

ลอง run ดู
Main> add_ints 1 7
8
Main> (add_ints 2) 4
6


ใครสนใจอ่าน currying ต่อได้ใน wikipedia

Related link from Roti

2 comments:

jittat said...

ใน ML ก็เป็นแบบนั้นเหมือนกันครับ เหมือนจะเรียกว่า partially instantiated function... เห็นครั้งแรกผมตกใจมาก
(แล้วก็เอาไปให้นักเรียนตกใจด้วยเหมือนกัน)

:)

PPhetra said...

ใช่ครับ อารมณ์เดียวกัน
เห็นแล้วตกใจ
ต้องรีบบอกคนอื่น