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 ครับ