4. Hàm trong Haskell
4.3 Tính không chặt của hàm
Xem xét ví dụ về cách định nghĩa sau cho hàm bot:
bot = bot
Với định nghĩa này, bot là biểu thức không kết thúc, giá trị của một biểu thức không kết thúc được ký hiệu là ⊥.
Hàm f được gọi là chặt (strict) nếu như khi nó được sử dụng với một biểu thức không có kết thúc, hàm này trả lại lỗi không kết thúc. Trong hầu hết các ngôn ngữ lập trình, các hàm đều là chặt. Tuy nhiên trong Haskell, hàm là không chặt.
Chẳng hạn như hàm const1 được định nghĩa như sau:
const1 x = 1
Khi đó const1 bot cho kết quả là 1. Điều này do const1 đã không cố gắng thực hiện đánh giá một hàm, nên không gặp phải lỗi không kết thúc. Những hàm không chặt được gọi là các “lazy function”, và các tham số đầu vào được gọi là “lazily”.
Trong Haskell, giá trị lỗi và giá trị không kết thúc về bản chất là giống nhau. Bởi vậy, cách tính const1 (1/0) cũng cho giá trị là 1.
Các hàm không chặt mang lại nhiều lợi ích. Chẳng hạn như nó đơn giản hóa cho người lập trình sự ràng buộc bởi thứ tự thực hiện. Những tính toán phức tạp sẽ được truyền như tham số cho các hàm, không cần phải lo lắng về việc phải chi phí cho những tính toán không cần thiết. Một ví dụ về sử dụng hàm không chặt đó là sử dụng với các cấu trúc dữ liệu không có điểm giới hạn (infinite).
Một cách giải thích nữa về hàm không chặt trong Haskell đó là Haskell sử dụng khái niệm định nghĩa (definition) thay cho việc sử dụng các phép gán như trong các ngôn ngữ lập trình truyền thống. Chẳng hạn như:
v = 1/0
được hiểu là “định nghĩa v là 1/0”, chứ không phải “tính toán 1/0 và lưu trữ kết quả vào biến v”. Cách định nghĩa này không thực hiện phép tính toán chia. Đối với các ngôn ngữ lập trình thông thường, người lập trình phải quan tâm đến thứ tự của các phép gán, bởi kết quả thu được phụ thuộc vào thứ tự này. Định nghĩa, ngược lại, cho phép những cách biểu diễn mà kết quả thu được không lệ thuộc vào thứ tự thực hiện.