Mở đầu về Haskell
Chúc mừng năm mới 2015 tới tất cả bạn đọc ktmt blog :) Chúc các bạn một năm mới coding thật productive! ^^
Năm mới chắc hẳn hầu hết mọi người đều có resolution của riêng mình. Một trong những resolution của tôi năm nay là học một ngôn ngữ lập trình mới, đến level có thể viết một chương trình không đơn giản với nó. (Bạn có thể tham khảo một danh sách các resolutions cho programmer ở đây). Ngôn ngữ mà tôi chọn là Haskell, một functional programming language, vì những ý tưởng trong ngôn ngữ lập trình này khác hẳn những ngôn ngữ lập trình tôi đã tiếp cận, như C/C++, Java, Python.
Tôi mới bắt đầu với Haskell được một vài tháng, và cảm thấy khá thích thú về những ý tưởng mới mẻ của nó. Tôi sẽ bắt đầu viết chia sẻ những kiến thức tôi thu thập được trong quá trình tìm hiểu ngôn ngữ này trên ktmt. Tuy nhiên, tôi phải nói trước là Haskell khá trừu tượng, và với một beginner như tôi, việc cố diễn giải các khái niệm khó của Haskell có thể sẽ không chính xác và dễ gây hiểu lầm. Vì thế, tôi sẽ tập trung vào viết những đoạn code để giải quyết một vấn đề to hoặc nhỏ nào đó và cố giải thích chúng làm được như thế bằng cách nào. Những khái niệm khó, tôi sẽ dẫn về những bài viết nổi tiếng để bạn đọc có thể tìm hiểu thêm.
Trong bài viết đầu tiên này, tôi sẽ hướng dẫn cách cài đặt những thành phần cơ bản để chúng ta có thể bắt đầu lập trình với Haskell. Cuối bài, sẽ có một chương trình Hello World rất đơn giản để chúng ta test xem môi trường của chúng ta đã hoàn thiện chưa.
Chú ý: Hiện tại tôi test trên máy tính của tôi (Windows 7). Tôi đã từng cài đặt môi trường trên Mac OS X và Ubuntu Linux, nhưng chưa có thời gian kiểm tra lại. Tôi sẽ thêm thông tin nếu cần thiết.
The Haskell Platform
Đây là cách đơn giản nhất để chúng ta có thể bắt đầu với Haskell. Trên Homepage, Haskell Platform được gọi là “Haskell: batteries included”. Trên homepage này, bạn có thể tải về cả package để cài đặt cho cả ba môi trường: Windows, Linux, Mac OS X. Sau khi cài đặt, bạn sẽ có rất nhiều thành phần tiêu chuẩn để bắt đầu lập trình với Haskell (List). Trong số đó, có những thành phần tiêu biểu sau:
GHC (Glassgow Haskell Compiler)
Đây là compiler cho Haskell.
GHCi
Đây là GHC interactive interpreter. Nếu bạn đã từng lập trình với Python hoặc Ruby, bạn có thể coi GHCi giống như khi bạn gõ python
(với Python) hoặc irb
(với Ruby) trên command line. GHCi cực kì hữu dụng trong quá trình bạn viết code Haskell.
Bạn sẽ dành khá nhiều thời gian trong GHCi, nên chúng ta sẽ dành chút thời gian để config GHCi sao cho thuận tiện nhất. File config của GHCi là .ghci
, vị trí của file này tùy thuộc vào hệ thống bạn đang sử dụng, bạn tham khảo ở đây: GHCi dot files. Tôi tạo mới một file .ghci
trong Home folder với nội dung:
1
|
|
Làm vậy, mỗi lần mở GHCi, prompt của bạn chỉ đơn giản là h>
chứ không phải là tên tất cả các module đã load (bạn hãy thử xem khác nhau như thế nào nếu không có dòng setting trên)
Cabal
Cabal là viết tắt của Common Architecture for Building Applications and Libraries
. Về chức năng, nó tương tự như pip
của Python hay gem
của Ruby, dùng để cài đặt những package chuẩn từ Hackage
(Haskell Central package archive). Những người viết package sử dụng Hackage
để publish các libraries hay programs của họ, và những Haskell programmer khác sử dụng các tool như cabal-install
để download và cài đặt các package này.
Trên Windows 7, mỗi khi sử dụng cabal, các package sẽ được install vào $HOME$\AppData\Roaming\cabal
. Trên Unix-based system, chúng được install vào ~/.cabal/
.
Sau đây là những thao tác đầu tiên bạn nên làm với cabal
:
1
|
|
Dùng để update list các package phiên bản mới nhất trên hackage.haskell.org
.
1
|
|
Dùng để update phiên bản cabal-install
mới nhất
Code Editor: Sublime Text
Bạn có thể dùng bất cứ một text editor nào để viết code Haskell. Nếu bạn sử dụng Sublime Text, bạn nên cài plugin SublimeHaskell. Đây là plugin hỗ trợ Cabal build, error and warning highlighting, smart completion và tích hợp ghc-mod. Bạn có thể tham khảo thêm thông tin tại GitHub repo
Cabal sandbox
Với Haskell, sandbox
cho phép chúng ta build các package một cách độc lập với package environment của hệ thống, bằng cách tạo ra một package environment riêng cho project hiện tại. Nếu bạn đã quen thuộc với Python’s virtualenv
hoặc Ruby’s RVM
, sandbox
là một khái niệm tương tự.
Bài viết này trình bày khá dễ hiểu về tại sao nên sử dụng sandbox
để tránh dependency hell, bạn có thể tham khảo thêm. Một số thao tác cơ bản với cabal sandbox gồm có:
1 2 3 4 |
|
Chú ý ở đây, cabal sandbox là một feature của cabal từ version 1.18 trở đi, cho nên sau khi init một sandbox hoàn toàn mới, các command tiếp theo (như build
hay install
) đều sẽ sử dụng sandbox chứ không phải package environment của hệ thống.
Ví dụ đầu tiên: Hello World
Chúng ta sẽ bắt đầu với ví dụ muôn thuở khi bắt đầu ngôn ngữ lập trình mới: In ra màn hình consle dòng chữ Hello World
.
1 2 3 |
|
cabal init
sẽ giúp chúng ta thêm thông tin cho project của mình, như: tên project, version, người phát triển, license,…
Tiếp theo, chúng ta edit file Cabal. Ví dụ sau khi edit, file haskell-hello-world.cabal
của tôi có nội dung như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Một số điểm lưu ý từ file cabal trên:
- Đặt
hs-source-dirs
là thư mụcsrc
để Cabal biết nơi lưu các file modules - Đặt
main-is
thànhMain.hs
để compiler biết đầu là main function của file binary build ra ghc-options
đặt thành-Wall
để chúng ta có thể thấy các Warning từ GHCbuild-depends
là nơi khai báo các library cần sử dụng, có thể kèm theo các option về yêu cầu version.
File code của chúng ta nằm ở src/Main.hs
có nội dung như sau:
1 2 3 |
|
Đây là một module rất đơn giản, và vì nó được dùng làm target cho main-is
, nó phải có một function tên main
và tên của module cũng phải tên là Main
. Hiện tại, bạn chưa cần để ý vội đến cú pháp mà chỉ cần biết rằng chương trình in ra màn hình dòng chữ “Hello World!”. (Chú ý: Có thể bạn sẽ nghĩ putStrLn
tương tự như printf
hay cout
ở C/C++, nhưng với Haskell, nguyên lý sẽ khác hơn so với bạn nghĩ, nhưng đó là câu chuyện ở những bài viết sau này.)
Tiếp theo, chúng ta tạo một Cabal sandbox để chứa toàn bộ các dependencies (ví dụ Hello World này của tôi hơi trivial, vì không dùng library nào cả, nhưng vì tính đầy đủ, tôi vẫn xin trình bày về sandbox ở đây):
1
|
|
Sau bước này, chúng ta sẽ có file cabal.sandbox.config
chứa thông tin về package environment, và sandbox nằm ở thư mục .cabal-sandbox
1 2 |
|
Nếu build thành công, bạn sẽ có file binary haskell-hello-world
ở dist/build/haskell-hello-world
. Thử chạy nó xem sao:
1 2 |
|
Và chúng ta đã build thành công program đầu tiên!
Kết luận
Bài viết này là bài viết đầu tiên của tôi về Haskell. Chưa có gì nhiều về syntax, idea, concept, mà chỉ là những setup ban đầu để dễ dàng bắt đầu với Haskell. Trong những bài viết tiếp theo, tôi sẽ cố gắng từng bước một trình bày các ý tưởng của Haskell một cách dễ hiểu.
Hẹn gặp lại!