Haskell - Mô hình dữ liệu cơ bản

Haskell là một ngôn ngữ lập trình chức năng thuần túy, do đó nó 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 (https://www.tutorialspoint.com/codingground.htm).

Số

Haskell đủ thông minh để giải mã một số nào đó dưới dạng số. Do đó, bạn không cần đề cập đến kiểu của nó 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 đơ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 đầ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.

Chuỗi

A stringkhông là gì ngoài một tập hợp các nhân vật. Không có cú pháp cụ thể để sử dụng chuỗi, nhưng Haskell tuân theo phong cách truyền 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 tôi đang chuyển chuỗi “Tutorialspoint.com”.

Prelude> :t "tutorialspoint.com"

Nó sẽ tạo ra kết quả sau trên màn hình:

"tutorialspoint.com" :: [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ẽ 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, Listcũ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à 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 phải 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]

Danh sách trong Haskell có bản chất là đồng nhất, có nghĩa là chúng sẽ không cho phép bạn khai báo 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 sử dụng biểu thức toán học này được gọi là List Comprehension.

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 biết đến như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ộ số được biểu diễn bằng 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 number loại biến và một char biến kiểu.