Haskell là một ngôn ngữ lập trình chức năng thuần túy, do đó nó có tính tương tác và thông minh hơn nhiều so với các ngôn ngữ lập trình khác. Trong chương này, chúng ta sẽ tìm hiểu về các mô hình dữ liệu cơ bản của Haskell thực sự được xác định trước hoặc bằng cách nào đó được giải mã một cách thông minh vào bộ nhớ máy tính.
Trong suốt hướng dẫn này, chúng tôi sẽ sử dụng nền tảng trực tuyến Haskell có sẵn trên trang web của chúng tôi
Con số
Haskell đủ thông minh để giải mã một số nào đó dưới dạng một số. Do đó, bạn không cần phải đề cập đến kiểu của nó ra bên ngoài như chúng ta thường làm trong trường hợp các ngôn ngữ lập trình khác. Theo ví dụ, hãy truy cập dấu nhắc lệnh dạo đầu của bạn và chỉ cần chạy “2 + 2” và nhấn enter.
sh-4.3$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> 2+2
Kết quả là bạn sẽ nhận được kết quả sau.4
Trong đoạn mã trên, chúng tôi chỉ chuyển hai số làm đối số cho trình biên dịch GHCI mà không xác định trước kiểu của chúng, nhưng trình biên dịch có thể dễ dàng giải mã hai mục này dưới dạng số.
Bây giờ, chúng ta hãy thử một phép tính toán học phức tạp hơn một chút và xem liệu trình biên dịch thông minh của chúng ta có cung cấp cho chúng ta kết quả chính xác hay không. Hãy thử với “15+ (5 * 5) -40”
Prelude> 15+(5*5)-40
Biểu thức trên mang lại “0” theo đầu ra mong đợi. 0
Nhân vật
Giống như các con số, Haskell có thể xác định một cách thông minh một ký tự được đưa vào làm đầu vào cho nó. Đi tới dấu nhắc lệnh Haskell của bạn và nhập bất kỳ ký tự nào có dấu ngoặc kép hoặc dấu nháy đơn.
Hãy để chúng tôi cung cấp dòng sau làm đầu vào và kiểm tra đầu ra của nó.
Prelude> :t "a"
Nó sẽ tạo ra kết quả sau:
"a" :: [Char]
Hãy nhớ rằng bạn sử dụng (: t ) trong khi cung cấp đầu vào. Trong ví dụ trên, (: t) là bao gồm loại cụ thể liên quan đến các đầu vào. Chúng ta sẽ tìm hiểu thêm về loại này trong các chương sắp tới. Hãy xem ví dụ sau, nơi chúng tôi đang chuyển một số đầu vào không hợp lệ dưới dạng ký tự, điều này dẫn đến lỗi.
Prelude> :t a
<interactive>:1:1: Not in scope: 'a'
Prelude> a
<interactive>:4:1: Not in scope: 'a'
Bằng thông báo lỗi “<interactive>: 4: 1: Not in scope:` a ‘”, trình biên dịch Haskell đang cảnh báo chúng tôi rằng nó không thể nhận dạng đầu vào của bạn. Haskell là một loại ngôn ngữ mà mọi thứ được biểu diễn bằng một con số. Haskell tuân theo kiểu mã hóa ASCII thông thường. Chúng ta hãy xem ví dụ sau để hiểu thêm –
Prelude> '\97'
'a'
Prelude> '\67'
'C
Xem cách đầu vào của bạn được giải mã thành định dạng ASCII.
Sợi dây
Một chuỗi không là gì ngoài một tập hợp các ký tự. Không có cú pháp cụ thể để sử dụng chuỗi, nhưng Haskell tuân theo phong cách thông thường là biểu diễn một chuỗi với dấu ngoặc kép.
Hãy xem ví dụ sau, nơi chúng ta đang chuyển chuỗi “dongthoigian.net”.
Prelude> :t " dongthoigian.net "
Nó sẽ tạo ra kết quả sau trên màn hình:
" dongthoigian.net " :: [Char]
Xem cách toàn bộ chuỗi đã được giải mã dưới dạng một mảng chỉ Char. Hãy để chúng tôi chuyển sang kiểu dữ liệu khác và cú pháp của nó. Khi chúng tôi bắt đầu thực hành thực tế, chúng tôi sẽ có thói quen với tất cả các loại dữ liệu và việc sử dụng nó.
Boolean
Kiểu dữ liệu Boolean cũng khá đơn giản giống như kiểu dữ liệu khác. Hãy xem ví dụ sau, nơi chúng ta sẽ sử dụng các phép toán Boolean khác nhau bằng cách sử dụng một số đầu vào Boolean như "True" hoặc "False".
Prelude> True && True
True
Prelude> True && False
False
Prelude> True || True
True
Prelude> True || False
True
Trong ví dụ trên, chúng ta không cần đề cập rằng “True” và “False” là các giá trị Boolean. Bản thân Haskell có thể giải mã nó và thực hiện các thao tác tương ứng. Hãy để chúng tôi sửa đổi đầu vào của chúng tôi bằng “true” hoặc “false”.
Prelude> true
Nó sẽ tạo ra kết quả sau:
<interactive>:9:1: Not in scope: 'true'
Trong ví dụ trên, Haskell không thể phân biệt giữa giá trị “true” và giá trị số, do đó đầu vào của chúng ta “true” không phải là số. Do đó, trình biên dịch Haskell gặp lỗi cho biết rằng đầu vào của chúng tôi không thuộc phạm vi của nó.
Danh sách và Tổng hợp danh sách
Giống như các kiểu dữ liệu khác, List cũng là một kiểu dữ liệu rất hữu ích được sử dụng trong Haskell. Theo ví dụ, [a, b, c] là một danh sách các ký tự, do đó, theo định nghĩa, Danh sách là một tập hợp có cùng kiểu dữ liệu được phân tách bằng dấu phẩy.
Giống như các kiểu dữ liệu khác, bạn không cần khai báo Danh sách dưới dạng Danh sách. Haskell đủ thông minh để giải mã đầu vào của bạn bằng cách xem cú pháp được sử dụng trong biểu thức. Hãy xem ví dụ sau đây cho thấy cách Haskell xử lý một Danh sách.
Prelude> [1,2,3,4,5]
Nó sẽ tạo ra kết quả sau:
[1,2,3,4,5]
Các danh sách trong Haskell có bản chất đồng nhất, có nghĩa là chúng sẽ không cho phép bạn khai báo một danh sách kiểu dữ liệu khác nhau. Bất kỳ danh sách nào như [1,2,3,4,5, a, b, c, d, e, f] sẽ tạo ra lỗi.
Prelude> [1,2,3,4,5,a,b,c,d,e,f]
Mã này sẽ tạo ra lỗi sau:
<interactive>:17:12: Not in scope: 'a'
<interactive>:17:14: Not in scope: 'b'
<interactive>:17:16: Not in scope: 'c'
<interactive>:17:18: Not in scope: 'd'
<interactive>:17:20: Not in scope: 'e'
<interactive>:17:22: Not in scope: 'f'
Danh sách hiểu
Hiểu danh sách là quá trình tạo một danh sách bằng cách sử dụng biểu thức toán học. Hãy xem ví dụ sau, nơi chúng ta đang tạo một danh sách bằng cách sử dụng biểu thức toán học ở định dạng [output | phạm vi, điều kiện].
Prelude> [x*2| x<-[1..10]]
[2,4,6,8,10,12,14,16,18,20]
Prelude> [x*2| x<-[1..5]]
[2,4,6,8,10]
Prelude> [x| x<-[1..5]]
[1,2,3,4,5]
Phương pháp tạo một Danh sách bằng cách sử dụng biểu thức toán học này được gọi là Tổng hợp Danh sách .
Tuple
Haskell cung cấp một cách khác để khai báo nhiều giá trị trong một kiểu dữ liệu duy nhất. Nó được gọi là Tuple . Một Tuple có thể được coi là một Danh sách, tuy nhiên có một số khác biệt về kỹ thuật giữa Tuple và một Danh sách.
Tuple là một kiểu dữ liệu bất biến, vì chúng ta không thể sửa đổi số lượng phần tử trong thời gian chạy, trong khi Danh sách là một kiểu dữ liệu có thể thay đổi.
Mặt khác, Danh sách là một kiểu dữ liệu đồng nhất, nhưng Tuple không đồng nhất về bản chất, bởi vì một Tuple có thể chứa các kiểu dữ liệu khác nhau bên trong nó. Các bộ giá trị được biểu diễn bằng một dấu ngoặc đơn. Hãy xem ví dụ sau để biết cách Haskell đối xử với Tuple.
Prelude> (1,1,'a')
Nó sẽ tạo ra kết quả sau:
(1,1,'a')
Trong ví dụ trên, chúng tôi đã sử dụng một tuple với hai số biến loại, và một char loại biến.