Khóa học ngôn ngữ lập trình Haskell

10 weeks
All levels
24 lessons
0 quizzes
0 students
Ngôn ngữ lập trình Haskell là ngôn ngữ polymorphic, statically typed, purely functional và lazy with type inference. Khóa học này giới thiệu về ngôn ngữ lập trình Haskell cùng với các đặc tính của mô hình lập trình chức năng, nếu bạn đã từng lập trình các ngôn ngữ mệnh lệnh như C++, Java, PHP… thì sẽ dễ tiếp thu hơn khi học seri bài giảng này!

Tại sao Cardano lại chọn Haskell?

Nếu bạn đã tham gia vào hệ sinh thái Cardano một thời gian, bạn có thể biết rằng blockchain của chúng tôi được xây dựng bằng ngôn ngữ lập trình chức năng có tên là ‘Haskell’. Haskell là cơ sở cho Plutus, ngôn ngữ lập trình hợp đồng thông minh của Cardano và nó cũng cung cấp năng lượng cho Marlowe, ngôn ngữ dành riêng cho cho các hợp đồng thông minh tài chính viết trên nền tảng Blockchain Cardano. Tuy nhiên, Haskell không phải là một trong những ngôn ngữ lập trình nổi tiếng nhất. Nó cũng không được đón nhận rộng rãi bởi những người mới bắt đầu trong hành trình của họ với tư cách là một nhà phát triển. Trên thực tế, ‘Chỉ số ngôn ngữ lập trình phổ biến xếp Haskell là ngôn ngữ được tìm kiếm nhiều thứ 27 trên Google tính đến tháng 11 năm 2020, với Python và Java chiếm các vị trí hàng đầu. Vì vậy, với suy nghĩ này, nhiều người có thể thắc mắc tại sao Cardano lại được triển khai ở Haskell ngay từ đầu? Lý do là Haskell, đặc biệt là kết hợp với các phương thức chính thức, rất thích hợp để viết mã mạnh mẽ và chính xác. Nhưng để hiểu tại sao điều này lại quan trọng đối với Cardano, trước tiên chúng ta cần khám phá Haskell là gì và xem xét vai trò của nó như một ngôn ngữ lập trình chức năng.

Vậy Haskell là gì?

Haskell là một ngôn ngữ lập trình hàm thuần túy. Trong các ngôn ngữ lập trình kiểu mệnh lệnh, bạn giải quyết vấn đề bằng cách đưa ra cho máy tính một loạt những nhiệm vụ để máy tính thực hiện chúng. Khi thực hiện, nó có thể thay đổi trạng thái. Chẳng hạn, bạn đặt biến a bằng 5 rồi làm công việc nào đó, rồi lại gán nó bằng một giá trị khác. Bạn có quyền điều khiển các cấu trúc lặp để thực hiện một thao tác vài lần. Trong ngôn ngữ lập trình hàm thuần túy, bạn không ra lệnh cho máy tính làm như vậy, mà là nói cho máy biết cần phải làm điều gì. Giai thừa của một số là tích các số nguyên từ 1 lên đến số đó; tổng của một danh sách các số thì bằng số thứ nhất cộng với tổng của tất cả các số còn lại, và cứ như vậy. Bạn thể hiện điều này dưới dạng các hàm. Bạn cũng không thể gán một biến bằng một giá trị nào đó để rồi sau này gán một giá trị khác. Nếu bạn nói rằng a bằng 5, sau này bạn sẽ không thể nói nó bằng gì khác hơn vì bạn đã nói nó bằng 5 rồi. Nếu không, chẳng phải bạn đã nói dối ư? Vì vậy trong các ngôn ngữ lập trình hàm, một hàm không có hiệu ứng phụ nào. Điều duy nhất mà hàm thực hiện là tính một thứ gì dó rồi trả lại giá trị. Thoạt đầu, điều này có vẻ hạn chế nhưng thực ra nó có một số hệ quả rất hay: nếu một hàm được gọi hai lần với các tham số giống hệt thì nó sẽ đảm bảo trả lại cùng kết quả. Điều này được gọi là sự minh bạch trong tham chiếu và không chỉ cho phép các trình biên dịch hiểu được động thái của chương trình, mà còn giúp bạn dễ dàng suy luận (và thậm chỉ cả chứng minh) ràng một hàm được viết đúng, để từ đó xây dựng những hàm phức tạp hơn bằng cách gắn kết những hàm đơn giản lại với nhau. Haskell có tính lười biếng. Điều này nghĩa là chỉ trừ khi bạn nói cụ thể ra, thì Haskell sẽ không thực thi các hàm và tính toán, cho đến khi nó thực sự bị buộc phải trưng kết quả ra cho bạn xem. Đặc tính này kết hợp tốt với sự minh bạch về tham chiếu; nó giúp cho bạn hình dung chương trình như là một loạt những phép biến đổi dữ liệu. Nó cho phép tồn tại những điều thú vị như cấu trúc dữ liệu vô hạn. Giả sử bạn có một danh sách cố định gồm các số xs = [1,2,3,4,5,6,7,8] và một hàm doubleMe có nhiệm vụ nhân mỗi phần tử lên 2 lần rồi trả lại một danh sách mới. Nếu ta muốn nhân danh sách này lên 8 lần, bằng cách dùng ngôn ngữ lập trình mệnh lệnh, và viết doubleMe(doubleMe(doubleMe(xs))), thì có thể nó đã duyệt qua danh sách một lần để tạo một bản sao rồi trả lại danh sách. Sau đó nó sẽ duyệt qua danh sách 2 lần nữa và trả lại kết quả. Trong một ngôn ngữ lập trình lười biếng, việc gọi doubleMe đối với một danh sách mà không yêu cầu phải trưng ra kết quả thì chương trình sẽ kiểu như đáp lời bạn “Rồi rồi, tôi sẽ làm sau!”. Nhưng một khi bạn muốn xem kết quả, thì doubleMe đầu tiên sẽ nói cho cái thứ hai biết rằng nó muốn kết quả, ngay bây giờ! Cái thứ hai sẽ nói cho cái thứ ba và cái thứ ba miễn cưỡng trả lại số gấp đôi của 1, tức là 2. Cái thứ hai nhận lấy giá trị này và đưa số 4 cho cái thứ nhất. Cái thứ nhất nhận lại và báo với bạn rằng phần tử đầu tiên cần tính là 8. Như vậy chỉ có một lần duyệt qua danh sách và chỉ khi bạn thực sự thấy cần. Bằng cách này khi bạn muốn một điều gì đó từ ngôn ngữ lập trình lười biếng, bạn có thể lấy số liệu đầu vào và chuyển đổi theo cách hiệu qủa rồi gắn lại thì sẽ được kết quả mong muốn ở đầu ra. Haskell có kiểu tĩnh. Khi bạn biên dịch chương trình vừa viết, thì trình biên dịch sẽ hiểu được đoạn mã nào là một số, đoạn mã nào là một chuỗi kí tự, vân vân. Điều này đồng nghĩa với việc rất nhiều lỗi tiềm ẩn được phát hiện lúc biên dịch. Nếu bạn cố gắng cộng một số và một chuỗi kí tự lại với nhau, trình biên dịch sẽ gào lên. Haskell sử dụng một hệ thống kiểu rất tốt và có khả năng suy luận kiểu. Nghĩa là bạn không cần phải gắn cụ thể từng đoạn mã lệnh với một kiểu riêng, vì hệ thống kiểu có thể hình dung ra điều này một cách rất thông minh. Nếu bạn nói a = 5 + 4, bạn sẽ không cần phải bảo Haskell biết rằng a là một con số; nó có thể tự hình dung ra được. Suy luận kiểu cũng giúp cho mã lệnh bạn viết được tổng quát hơn. Nếu như một hàm bạn viết ra nhận hai tham số và cộng chúng lại với nhau mà không nói rõ kiểu của các tham số này thì hàm sẽ tính được với hai tham số bất kì nào có biểu hiện giống kiểu số. Haskell tinh tế và gọn. Vì dùng nhiều khái niệm cấp cao, những chương trình Haskell thường ngắn hơn các chương trình tương đương viết theo ngôn ngữ mệnh lệnh. Và những chương trình ngắn thì dễ bảo trì hơn và ít lỗi hơn so với những chương trình dài. Haskell được tạo ra bởi những người rất thông minh (có bằng tiến sĩ). Việc thiết lập Haskell bắt đầu vào năm 1987 khi một hội đồng những nhà nghiên cứu hợp tác để thiết kế nên một ngôn ngữ thật ấn tượng. Năm 2003, bản Haskell Report được xuất bản, định hình phiên bản ổn định của ngôn ngữ này

Bạn cần gì để bắt đầu?

Một trình soạn file chữ và trình biên dịch Haskell. Bạn có thể đã có một trình soạn file chữ ưa thích vì vậy ta sẽ không mất thời gian bàn về nó nữa. Để thực hành nội dung trong cuốn sách này ta sẽ dùng GHC, trình biên dịch Haskell thông dụng nhất. Cách tốt nhất để bắt đầu là tải về Haskell Platform, nói nôm na đây là Haskell với các thư viện phụ thêm. GHC có thể nhận một đoạn chương trình Haskell (thường có phần mở rộng .hs) để biên dịch, tuy vậy nó cũng có một chế độ tương tác vốn cho phép bạn tương tác trực tiếp với các đoạn chương trình. Tương tác. Bạn có thể gọi các hàm từ đoạn chương trình được tải và kết quả sẽ được hiển thị tức thì. Để phục vụ mục đích học tập thì cách này dễ và nhanh hơn nhiều so với phải biên dịch mỗi khi bạn sửa đổi rồi chạy lại từ dấu nhắc lệnh. Chế độ văn lệnh được khởi động bằng cách gõ vào ghci từ dấu nhắc hệ thống. Nếu bạn đã định nghĩa một số hàm trong một file có tên ví dụ như là myfunctions.hs, thì bạn sẽ tải các hàm này bằng cách gõ vào :l myfunctions; xong rồi bạn có thể thử nghiệm chúng, miễn là myfunctions.hs được đặt ở cùng thư mục nơi mà ghci được khởi động. Nếu bạn sửa đổi file chương trình .hs, thì chỉ cần gõ lại :l myfunctions hoặc gõ :r; cách làm này tương đương vì nó tải lại (reload) file chương trình hiện thời. Quy trình hoạt động quen thuộc với tôi khi thử nghiệm là định nghĩa một hàm nào đó trong một file .hs, tải nó rồi thử chạy chán chê, sau đó sửa đổi file .hs file, tải lại và cứ như vậy. Đây cũng là cách mà chúng ta sẽ làm

Tài liệu tham khảo bằng Tiếng Việt: Learn You a Haskell for Great Good! Hướng dẫn cho người mới bắt đầu

Haskell rất thú vị và dưới đây là những điều bạn cần biết về Haskell Cuốn sách hướng dẫn này chủ yếu dành cho những người đã có kinh nghiệm lập trình những ngôn ngữ mệnh lệnh (C, C++, Java, Python …) nhưng trước đây chưa dùng ngôn ngữ lập trình hàm (Haskell, ML, OCaml …). Dù vậy tôi vẫn dám cá với bạn rằng nếu bạn không chưa có kinh nghiệm lập trình gì đáng kể, một người thông minh như bạn vẫn có thể theo kịp nội dung và học được Haskell. Trước khi nắm được Haskell tôi đã thất bại chừng 2 lần vì có vẻ như nó quá kì quặc đối với mình và tôi không hiểu được. Nhưng rồi một khi đã “vào guồng” và vượt qua rào cản ban đầu đó, mọi chuyện đều thuận buồn xuôi gió. Tôi đoán rằng điều tôi muốn nói sẽ là: Haskell thật thuyệt và nếu bạn quan tâm đến lập trình thì bạn thực sự nên học ngôn ngữ này ngay cả khi ban đầu nó có vẻ kì quặc. Học Haskell cũng rất giống với lần đầu học lập trình — thật là vui! Nó bắt bạn phải suy nghĩ khác đi, điều mà sẽ dẫn ta đến mục kế tiếp … *Ghi chú Nếu bạn gặp phải vấn đề khi học Haskell thì hastag #haskell trên freenode là một nơi tốt để bạn đặt câu hỏi mỗi khi bị bí trong lập trình. Mọi người ở đó đều tốt bụng, kiên nhẫn, và cảm thông đối với những người mới học. Tải sách miễn phí tại: https://vneconomics.com/wp-content/uploads/2022/12/Learn-You-a-Haskell-for-Great-Good-Huong-dan-cho-nguoi-moi-bat-dau.pdf 

Đăng ký nhận bài viết mới nhất từ VNEconomics Academy

Long Nguyen
Official channels: https://www.youtube.com/user/logauit