วงแหวนเว็บ

neizod's speculation

insufficient data for meaningful answer

เปลี่ยนค่าตัวแปรใน Haskell

Friday, November 30, 2012, 02:09 PM

ใน ghci ถ้าเราลองทำอย่างนี้

let x = 10
let x = x + 1

กด Enter แล้วจะพบ prompt รอทำงานต่อ ถึงตอนนี้อาจคิดว่าไม่มีปัญหาหนิ แต่อย่าลืมว่า Haskell เป็น lazy language ดังนั้นต้องเรียก x ออกมาดูค่าด้วย

… แล้วเราก็จะพบกับความว่างเปล่า เฮ้ยทำไมแค่บวกเลขง่ายๆ มันถึงคิดช้าจังฟระ

นั่นเป็นเพราะว่ารูปด้านบนนี้เป็น recursive ตอนที่จะ eval ค่า x + 1 ด้านขวามือออกมา มันจะไปเรียกดู definition ของ x ซึ่งก็คือ x + 1 นั่นเอง (ลืมไปได้เลยว่าเราเคยบอกให้ x = 10)

อย่างไรก็ตาม ถ้าเราเปลี่ยนไปเขียนแบบนี้

let x = 10
let y = x + 1
let x = y

เวลาเรียก x เราจะได้คำตอบที่ถูกต้องคือ 11 แล้วครับ


แต่ถ้าทำท่าข้างบนนี้ มันก็คงบาปพอๆ กับ

word = "abracadabra"
for i in range(len(word)):
    print(word[i])

ใน Python นั่นแหละ :P


ดังนั้น Haskell จะเลี่ยงไปใช้ Monad แทน

x <- return 10
x <- return (x + 1)

ดูเผินๆ เหมือนว่าเราจะเปลี่ยนค่าตัวแปร x ได้ แต่ที่จริงแล้วสองบรรทัดข้างบนนี้จะเทียบเท่ากับ

return 10 >>= \x -> return (x + 1) >>= \x -> return x

นั่นหมายความว่า แรกสุดเราเอาค่า 10 ส่งให้ฟังก์ชั่นที่รับตัวแปร 1 ตัว โดยฟังก์ชั่นนี้อ่านชื่อตัวแปรที่รับมาว่า x แล้วจึงคำนวณ x + 1 เรียบร้อยแล้วก็ส่งต่อค่าที่คำนวณได้ไปให้ฟังก์ชั่นอีกตัว ที่รับตัวแปร 1 ตัวและอ่านชื่อตัวแปรนั้นว่า x เช่นกัน

จะเห็นว่าแท้จริงแล้วเราไม่ได้เปลี่ยนค่าของตัวแปรเลย มันเป็นเพียงการส่งต่อค่าที่คำนวณแล้วให้ฟังก์ชันอื่นไปเรื่อยๆ โดยที่ฟังก์ชั่นเหล่านั้นบังเอิญเรียกชื่อตัวแปรเหมือนกันเท่านั้นเอง

neizod

author