Nattawut Phetmak
Jack of all Trades
ใน Haskell จะแบ่งข้อมูลตัวอักษรเป็น 2 แบบ ได้แก่ Char
(อักษร 1 ตัว) ที่ประกาศโดยใช้ single quote ส่วน String
(อักษรหลายตัว) ประกาศโดยใช้ double quote
ghci> let c = 'a'
ghci> let s = "abc"
อย่างไรก็ตาม ถ้าลองตรวจสอบ type ของ String จะเห็นแบบนี้
ghci> :t "this is a string"
"this is a string" :: [Char]
วงเล็บปีกแข็งที่ครอบ Char
นั้นบอกว่า String
เป็นข้อมูลแบบ List
ของ Char
(คือการเอา Char
หลายๆ ตัวมาต่อกัน)
การเชื่อม String
เข้าด้วยกัน ทำได้โดยวางเครื่องหมาย ++
ไว้ระหว่างข้อความ 2 ข้อความ
ghci> "Hello " ++ "Nick" ++ "."
"Hello Nick."
อย่างไรก็ตาม การเชื่อม String
กับ Char
ต้องแปลง type ของ Char
ให้เป็น String
เสียก่อน
ghci> "Grade: " ++ ['A']
"Grade: A"
ถ้าต้องการแสดงตัวเลข (และข้อมูลชนิดอื่นๆ) ให้ใช้ฟังก์ชัน show
แทน
ghci> "Point: " ++ show 87.5
"Point: 87.5"
ส่วนการแปลง type จากข้อความไปเป็น type อื่นเพื่อนำไปคำนวณต่อ สามารถทำได้ผ่านฟังก์ชัน read
เช่นนี้
ghci> read "23" + 19
42
แต่การสั่ง read "23"
เพียงอย่างเดียวจะเกิด error เพราะตัวแปรนั้นจะหา type ไม่ได้ (เนื่องจากไม่รู้ว่าจะถูกเอาไปใช้ทำอะไรต่อ)
ทางออกคือถ้ารู้ type ที่จะเอาไปใช้ต่อแน่นอน ก็กำหนดลงไปได้เลย
ghci> read "23" :: Float
23.0
เนื่องจากหลักการของภาษาเชิง functional นั้นบอกว่า ฟังก์ชันใดๆ ที่เรียกขึ้นมาโดยส่งผ่านตัวแปรเดิมเข้าไป ผลลัพท์ก็ต้องออกมาเหมือนเดิมเสมอ
ตัวแปรของฟังก์ชันในที่นี้ คือตัวแปรที่กำหนดโดยโปรแกรมเมอร์ ไม่ใช่ IO จากฝั่งผู้ใช้ ดังนั้นถ้ายึดตามหลักนี้ โปรแกรมเดียวกันจะให้ผลลัพท์เดิมทุกครั้ง (เพราะ IO ที่รับมาจากผู้ใช้ไม่มีความหมาย) Haskell แก้ปัญหานี้โดยการนิยามฟังก์ชันสำหรับจัดการ IO แยกออกมาโดยเฉพาะ
เมื่อต้องการรับข้อความเป็นบรรทัดจากผู้ใช้ ทำได้โดยฟังก์ชัน getLine
ดังนี้
ghci> input <- getLine
ฟังก์ชันนี้จะรอเราพิมพ์ข้อความไปเรื่อยๆ จนกว่าจะป้อน EOL ให้ สังเกตว่าการเก็บผลลัพท์นั้นไม่ได้ใช้ let
แล้วตามด้วย =
แล้ว แต่เปลี่ยนมาใช้ <-
แทน ซึ่งเป็นสัญลักษณ์พิเศษสำหรับเก็บค่า String
ที่รับมาจาก IO ครับ
อนึ่ง การพิมพ์ค่าโดยฟังก์ชัน putStrLn
นั้น ตัวแปรแบบต้องเป็นข้อความเท่านั้น ถ้าต้องการพิมพ์ค่าตัวแปรที่ไม่ใช่ข้อความ สามารถใช้ฟังก์ชัน print
แทนได้
ตัวอย่างต่อไปนี้เป็นโปรแกรมแบบ IO คอยรับข้อมูลจากผู้ใช้ แล้วคำนวณด้านที่ยาวที่สุดของสามเหลี่ยมมุมฉากครับ
main = do
putStrLn "what is x?"
x <- getLine
putStrLn "what is y?"
y <- getLine
putStrLn "then z is:"
print (sqrt ((read x)**2 + (read y)**2))
main
หมายเหตุว่าการ recursive main
นั้นเป็นเรื่องปรกติใน Haskell ครับ