Danh sách python giai thừa

Haskell là một Ngôn ngữ lập trình hàm được thiết kế đặc biệt để xử lý các ứng dụng xử lý danh sách và tính toán tượng trưng. Lập trình hàm dựa trên các hàm toán học. Ngoài Haskell, một số ngôn ngữ phổ biến khác tuân theo mô hình Lập trình hàm bao gồm. Lisp, Python, Erlang, Vợt, F #, Clojure, v.v.

Trong lập trình thông thường, các lệnh được coi là một tập hợp các khai báo theo một cú pháp hoặc định dạng cụ thể, nhưng trong trường hợp lập trình chức năng, tất cả các tính toán được coi là sự kết hợp của các hàm toán học riêng biệt.

Hoạt động với Haskell

Haskell là một ngôn ngữ chức năng thuần túy được sử dụng rộng rãi. Ở đây, chúng tôi đã liệt kê một số điểm khiến ngôn ngữ này trở nên đặc biệt hơn so với các ngôn ngữ lập trình thông thường khác như Java, C, C++, PHP, v.v.

  • Ngôn ngữ chức năng − Trong ngôn ngữ lập trình thông thường, chúng tôi hướng dẫn trình biên dịch một loạt các tác vụ không gì khác ngoài việc nói với máy tính của bạn "phải làm gì" và "làm như thế nào?"

  • Sự lười biếng - Haskell là một ngôn ngữ lười biếng. Bằng cách lười biếng, chúng tôi muốn nói rằng Haskell sẽ không đánh giá bất kỳ biểu thức nào mà không có lý do. Khi công cụ đánh giá thấy rằng một biểu thức cần được đánh giá, thì nó sẽ tạo cấu trúc dữ liệu thunk để thu thập tất cả thông tin cần thiết cho đánh giá cụ thể đó và một con trỏ tới cấu trúc dữ liệu thunk đó. Công cụ đánh giá sẽ chỉ bắt đầu hoạt động khi được yêu cầu đánh giá biểu thức cụ thể đó

  • Tính mô đun - Một ứng dụng Haskell không là gì ngoài một loạt các chức năng. Có thể nói rằng một ứng dụng Haskell là một tập hợp của nhiều ứng dụng Haskell nhỏ

  • Nhập tĩnh - Trong ngôn ngữ lập trình thông thường, chúng ta cần xác định một loạt các biến cùng với loại của chúng. Ngược lại, Haskell là một ngôn ngữ giao thoa kiểu. Theo thuật ngữ, ngôn ngữ giao thoa kiểu, ý chúng tôi là trình biên dịch Haskell đủ thông minh để tìm ra kiểu của biến được khai báo, do đó chúng ta không cần đề cập rõ ràng kiểu của biến được sử dụng

  • Khả năng bảo trì - Các ứng dụng Haskell là mô-đun và do đó, việc bảo trì chúng rất dễ dàng và tiết kiệm chi phí

Các chương trình chức năng đồng thời hơn và chúng tuân theo tính song song trong thực thi để cung cấp hiệu suất chính xác hơn và tốt hơn. Haskell cũng không ngoại lệ;

Chào thế giới

Đó là một ví dụ đơn giản để chứng minh tính năng động của Haskell. Hãy xem đoạn mã sau. Tất cả những gì chúng ta cần chỉ là một dòng để in "Xin chào Word" trên bảng điều khiển

main = putStrLn "Hello World"

Khi trình biên dịch Haskell gặp đoạn mã trên, nó sẽ nhanh chóng tạo ra đầu ra sau -

Hello World 

Chúng tôi sẽ cung cấp nhiều ví dụ xuyên suốt hướng dẫn này để giới thiệu sức mạnh và sự đơn giản của Haskell

Chúng tôi đã thiết lập môi trường lập trình Haskell trực tuyến tại - https. //www. hướng dẫn. com/compile_haskell_online. php

Trình chỉnh sửa trực tuyến này có nhiều tùy chọn để thực hành các ví dụ lập trình Haskell. Chuyển đến phần đầu cuối của trang và nhập "ghci". Lệnh này tự động tải trình biên dịch Haskell và khởi động Haskell trực tuyến. Bạn sẽ nhận được kết quả sau khi sử dụng lệnh ghci

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>

Nếu bạn vẫn muốn sử dụng Haskell ngoại tuyến trong hệ thống cục bộ của mình, thì bạn cần tải xuống thiết lập Haskell có sẵn từ trang web chính thức của nó – https. //www. haskell. tổ chức/tải xuống

Có ba loại trình cài đặt khác nhau có sẵn trên thị trường –

  • Trình cài đặt tối thiểu - Nó cung cấp GHC (Trình biên dịch Haskell của Glasgow), CABAL (Kiến trúc chung cho các ứng dụng và thư viện xây dựng) và các công cụ ngăn xếp

  • Trình cài đặt ngăn xếp − Trong trình cài đặt này, GHC có thể được tải xuống trên nhiều nền tảng của chuỗi thu phí được quản lý. Nó sẽ cài đặt ứng dụng của bạn trên toàn cầu để có thể cập nhật các công cụ API của nó bất cứ khi nào cần. Nó tự động giải quyết tất cả các phụ thuộc theo định hướng Haskell

  • Nền tảng Haskell - Đây là cách tốt nhất để cài đặt Haskell vì nó sẽ cài đặt toàn bộ nền tảng trong máy của bạn và từ một vị trí cụ thể. Bộ cài đặt này không phân phối như hai bộ cài đặt trên

Bây giờ chúng tôi đã thấy các loại trình cài đặt khác nhau có sẵn trên thị trường, hãy cho chúng tôi xem cách sử dụng các trình cài đặt đó trong máy của chúng tôi. Trong hướng dẫn này, chúng tôi sẽ sử dụng trình cài đặt nền tảng Haskell để cài đặt trình biên dịch Haskell trong hệ thống của chúng tôi

Thiết lập môi trường trong Windows

Để thiết lập môi trường Haskell trên máy tính Windows của bạn, hãy truy cập trang web chính thức của họ https. //www. haskell. tổ chức/nền tảng/cửa sổ. html và tải xuống Trình cài đặt theo kiến ​​trúc tùy chỉnh của bạn

Danh sách python giai thừa

Kiểm tra kiến ​​trúc hệ thống của bạn và tải xuống tệp thiết lập tương ứng và chạy nó. Nó sẽ cài đặt giống như mọi ứng dụng Windows khác. Bạn có thể cần cập nhật cấu hình CABAL của hệ thống

Thiết lập môi trường trong MAC

Để thiết lập môi trường Haskell trên hệ thống MAC của bạn, hãy truy cập trang web chính thức của họ https. //www. haskell. tổ chức/nền tảng/mac. html và tải xuống trình cài đặt Mac

Danh sách python giai thừa

Thiết lập môi trường trong Linux

Cài đặt Haskell trên hệ thống dựa trên Linux yêu cầu chạy một số lệnh không dễ dàng như MAC và Windows. Vâng, nó mệt mỏi nhưng nó đáng tin cậy

Bạn có thể làm theo các bước dưới đây để cài đặt Haskell trên hệ thống Linux của mình −

Bước 1 - Để thiết lập môi trường Haskell trên hệ thống Linux của bạn, hãy truy cập trang web chính thức https. //www. haskell. tổ chức/nền tảng/linux. html và chọn phân phối của bạn. Bạn sẽ tìm thấy màn hình sau trên trình duyệt của mình

Danh sách python giai thừa

Bước 2 - Chọn Phân phối của bạn. Trong trường hợp của chúng tôi, chúng tôi đang sử dụng Ubuntu. Sau khi chọn tùy chọn này, bạn sẽ nhận được trang sau trên màn hình với lệnh cài đặt Haskell trong hệ thống cục bộ của chúng tôi

Danh sách python giai thừa

Bước 3 - Mở terminal bằng cách nhấn Ctrl + Alt + T. Chạy lệnh "$ sudo apt-get install haskell-platform" và nhấn Enter. Nó sẽ tự động bắt đầu tải xuống Haskell trên hệ thống của bạn sau khi xác thực bạn bằng mật khẩu gốc. Sau khi cài đặt, bạn sẽ nhận được thông báo xác nhận

Bước 4 - Quay lại thiết bị đầu cuối của bạn và chạy lệnh GHCI. Khi bạn nhận được lời nhắc Prelude, bạn đã sẵn sàng sử dụng Haskell trên hệ thống cục bộ của mình

Danh sách python giai thừa

Để thoát khỏi prolog GHCI, bạn có thể sử dụng lệnh ". thoát ra"

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ã 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. hướng dẫn. com/codingground. htm)

số

Haskell đủ thông minh để giải mã một số thành một số. Do đó, bạn không cần đề cập đến loại 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 chuyển đến dấu nhắc lệnh mở đầ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 ta 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 loại của chúng, nhưng trình biên dịch có thể dễ dàng giải mã hai mục nhập này dưới dạng số

Bây giờ, chúng ta hãy thử tính toán 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 dự kiến

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ó. Chuyển đến 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 ngoặ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 đầu ra sau -

________số 8

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 char, từ đó dẫn đến lỗi

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 

Bởi thông báo lỗi ". 4. 1. Không trong phạm vi. `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 ra đầu vào của bạn. Haskell là một loại ngôn ngữ trong đó mọi thứ được biểu diễn bằng một 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 -

Hello World 
0

Xem cách đầu vào của bạn được giải mã thành định dạng ASCII

Chuỗi

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 để biểu diễn một chuỗi có 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”

Hello World 
1

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

Hello World 
2

Xem cách toàn bộ chuỗi đã được giải mã dưới dạng một mảng Char. Hãy 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à cách sử dụng nó

Boolean

Kiểu dữ liệu Boolean cũng khá đơn giản như các 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, chẳng hạn như "True" hoặc "False"

Hello World 
3

Trong ví dụ trên, chúng ta không cần đề cập đến "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 mình bằng "true" hoặc "false"

Hello World 
4

Nó sẽ tạo ra đầu ra sau -

Hello World 
5

Trong ví dụ trên, Haskell không thể phân biệt giữa "true" và một giá trị số, do đó "true" đầu vào của chúng tôi không phải là một số. Do đó, trình biên dịch Haskell đưa ra một lỗi cho biết rằng đầu vào của chúng ta không thuộc phạm vi của nó

Danh sách và danh sách hiểu

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 hay đượ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 kiểu dữ liệu giống nhau được phân tách bằng dấu phẩy

Cũng như các kiểu dữ liệu khác, bạn không cần khai báo List dưới dạng List. 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ý Danh sách

Hello World 
6

Nó sẽ tạo ra đầu ra sau -

Hello World 
7

Các danh sách trong Haskell về 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 một danh sách thuộc các loại 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

Hello World 
8

Mã này sẽ tạo ra lỗi sau -

Hello World 
9

Danh sách hiểu

Hiểu danh sách là quá trình tạo 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 tôi đang tạo danh sách bằng cách sử dụng biểu thức toán học ở định dạng [đầu ra. phạm vi, điều kiện]

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>
0

Phương pháp tạo một Danh sách này bằng cách sử dụng biểu thức toán học được gọi là Hiểu 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. Nó được gọi là Tuple. Tuple có thể được coi là List, tuy nhiên có một số khác biệt về kỹ thuật giữa Tuple và List

Tuple là kiểu dữ liệu không thể thay đổi, vì chúng ta không thể sửa đổi số lượng phần tử khi chạy, trong khi List là kiểu dữ liệu có thể thay đổi

Mặt khác, List là một kiểu dữ liệu đồng nhất, nhưng Tuple về bản chất là không đồng nhất, bởi vì một Tuple có thể chứa các loại dữ liệu khác nhau bên trong nó

Tuples được đại diện bởi dấu ngoặc đơn. Hãy xem ví dụ sau để xem Haskell xử lý một Tuple như thế nào

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>
1

Nó sẽ tạo ra đầu ra sau -

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>
2

Trong ví dụ trên, chúng ta đã sử dụng một Tuple với hai biến kiểu số và một biến kiểu char

Trong chương này, chúng ta sẽ tìm hiểu về các toán tử khác nhau được sử dụng trong Haskell. Giống như các ngôn ngữ lập trình khác, Haskell xử lý thông minh một số thao tác cơ bản như cộng, trừ, nhân, v.v. Trong các chương sắp tới, chúng ta sẽ tìm hiểu thêm về các toán tử khác nhau và cách sử dụng chúng

Trong chương này, chúng ta sẽ sử dụng các toán tử khác nhau trong Haskell bằng nền tảng trực tuyến của chúng ta (https. //www. hướng dẫn. com/codingground. htm). Hãy nhớ rằng chúng ta chỉ sử dụng các số kiểu số nguyên vì chúng ta sẽ tìm hiểu thêm về các số kiểu thập phân trong các chương tiếp theo

Toán tử cộng

Như tên gợi ý, toán tử cộng (+) được sử dụng cho hàm cộng. Mã mẫu sau đây cho thấy cách bạn có thể cộng hai số nguyên trong Haskell −

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>
3

Trong tệp trên, chúng tôi đã tạo hai biến riêng biệt var1 và var2. Cuối cùng, chúng tôi đang in kết quả bằng toán tử cộng. Sử dụng nút biên dịch và thực thi để chạy mã của bạn

Mã này sẽ tạo đầu ra sau trên màn hình -

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>
4

Toán tử trừ

Như tên gợi ý, toán tử này được sử dụng cho phép toán trừ. Mã mẫu sau đây cho thấy cách bạn có thể trừ hai số nguyên trong Haskell −

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>
5

Trong ví dụ này, chúng tôi đã tạo hai biến var1 và var2. Sau đó, chúng tôi sử dụng toán tử trừ (-) để trừ hai giá trị

Mã này sẽ tạo đầu ra sau trên màn hình -

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>
6

Toán tử nhân

Toán tử này được sử dụng cho phép toán nhân. Đoạn mã sau cho thấy cách nhân hai số trong Haskell bằng Toán tử nhân –

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>
7

Mã này sẽ tạo ra đầu ra sau, khi bạn chạy nó trong nền tảng trực tuyến của chúng tôi –

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>
8

Bộ phận điều hành

Hãy xem đoạn mã sau. Nó chỉ ra cách bạn có thể chia hai số trong Haskell −

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking.. done.
Loading package base...linking...done.
Prelude>
9

Nó sẽ tạo ra đầu ra sau -

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
0

Trình tự / Toán tử phạm vi

Sequence hoặc Range là một toán tử đặc biệt trong Haskell. Nó được ký hiệu là "(. )". Bạn có thể sử dụng toán tử này khi khai báo một danh sách với một chuỗi các giá trị

Nếu bạn muốn in tất cả các giá trị từ 1 đến 10, thì bạn có thể sử dụng một cái gì đó như "[1. 10]". Tương tự, nếu bạn muốn tạo tất cả các bảng chữ cái từ "a" đến "z", thì bạn chỉ cần gõ "[a. z]"

Đoạn mã sau cho biết cách bạn có thể sử dụng toán tử Sequence để in tất cả các giá trị từ 1 đến 10 −

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
1

Nó sẽ tạo ra đầu ra sau -

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
2

Ra quyết định là một tính năng cho phép các lập trình viên áp dụng một điều kiện trong luồng mã. Lập trình viên có thể thực hiện một tập hợp các hướng dẫn tùy thuộc vào điều kiện được xác định trước. Lưu đồ sau đây cho thấy cấu trúc ra quyết định của Haskell -

Danh sách python giai thừa

Haskell cung cấp các loại tuyên bố ra quyết định sau -

Sr. Không. Câu lệnh và Mô tả 1 Câu lệnh If–else

Một câu lệnh if với một câu lệnh khác. Lệnh trong khối khác sẽ chỉ thực thi khi điều kiện Boolean đã cho không thỏa mãn

2Câu lệnh if-else lồng nhau

Nhiều khối if theo sau bởi các khối khác

Haskell là một ngôn ngữ chức năng và nó được gõ nghiêm ngặt, có nghĩa là kiểu dữ liệu được sử dụng trong toàn bộ ứng dụng sẽ được trình biên dịch biết tại thời điểm biên dịch

Lớp loại sẵn có

Trong Haskell, mọi câu lệnh được coi là biểu thức toán học và danh mục của biểu thức này được gọi là Loại. Bạn có thể nói rằng "Kiểu" là kiểu dữ liệu của biểu thức được sử dụng tại thời điểm biên dịch

Để tìm hiểu thêm về Loại, chúng tôi sẽ sử dụng ". lệnh t". Theo một cách chung, Loại có thể được coi là một giá trị, trong khi Loại Loại có thể được coi là một tập hợp các Loại tương tự. Trong chương này, chúng ta sẽ tìm hiểu về các loại sẵn có khác nhau

số nguyên

Int là một lớp kiểu đại diện cho dữ liệu kiểu Số nguyên. Mọi số nguyên trong phạm vi từ 2147483647 đến -2147483647 đều thuộc lớp kiểu Int. Trong ví dụ sau, hàm fType() sẽ hoạt động theo kiểu được xác định

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
3

Ở đây, chúng tôi đã đặt loại hàm fType() là int. Hàm nhận hai giá trị int và trả về một giá trị int. Nếu bạn biên dịch và thực thi đoạn mã này, thì nó sẽ tạo ra đầu ra sau -

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
4

số nguyên

Số nguyên có thể được coi là siêu tập hợp của Int. Giá trị này không bị giới hạn bởi bất kỳ số nào, do đó Số nguyên có thể có độ dài bất kỳ mà không bị giới hạn. Để thấy sự khác biệt cơ bản giữa các kiểu Int và Integer, chúng ta hãy sửa đổi đoạn mã trên như sau -

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
5

Nếu bạn biên dịch đoạn mã trên, thông báo lỗi sau sẽ được đưa ra -

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
6

Lỗi này xảy ra do hàm fType() của chúng tôi mong đợi một giá trị kiểu Int và chúng tôi đang chuyển một giá trị kiểu Int lớn thực sự. Để tránh lỗi này, chúng ta hãy sửa kiểu "Int" bằng "Integer" và quan sát sự khác biệt

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
7

Bây giờ, nó sẽ tạo ra đầu ra sau -

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
8

Trôi nổi

Hãy xem đoạn mã sau. Nó cho thấy kiểu Float hoạt động như thế nào trong Haskell −

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
9

Hàm lấy hai giá trị float làm đầu vào và mang lại một giá trị float khác làm đầu ra. Khi bạn biên dịch và thực thi mã này, nó sẽ tạo ra đầu ra sau -

4
0

Gấp đôi

Double là một số dấu phẩy động với độ chính xác gấp đôi ở cuối. Hãy xem ví dụ sau -

4
1

Khi bạn thực thi đoạn mã trên, nó sẽ tạo ra kết quả sau -

4
2

bool

Bool là một kiểu Boolean. Nó có thể là Đúng hoặc Sai. Thực thi đoạn mã sau để hiểu cách hoạt động của kiểu Bool trong Haskell −

4
3

Ở đây, chúng tôi đang xác định một biến "x" là Bool và so sánh nó với một giá trị Boolean khác để kiểm tra tính nguyên bản của nó. Nó sẽ tạo ra đầu ra sau -

4
4

Char

Char đại diện cho nhân vật. Mọi thứ trong một trích dẫn đều được coi là Ký tự. Trong đoạn mã sau, chúng tôi đã sửa đổi hàm fType() trước đó của mình để chấp nhận giá trị Char và trả về giá trị Char làm đầu ra

4
5

Đoạn mã trên sẽ gọi hàm fType() với giá trị ký tự là 'v' nhưng nó trả về một giá trị ký tự khác, đó là 'K'. Đây là đầu ra của nó -

4
6

Lưu ý rằng chúng ta sẽ không sử dụng các kiểu này một cách rõ ràng vì Haskell đủ thông minh để nắm bắt kiểu trước khi nó được khai báo. Trong các chương tiếp theo của hướng dẫn này, chúng ta sẽ thấy các kiểu và lớp Kiểu khác nhau làm cho Haskell trở thành một ngôn ngữ được gõ mạnh như thế nào

Loại EQ

Lớp loại EQ là một giao diện cung cấp chức năng để kiểm tra sự bằng nhau của một biểu thức. Bất kỳ lớp Loại nào muốn kiểm tra sự bằng nhau của một biểu thức phải là một phần của Lớp Loại EQ này

Tất cả các lớp Loại tiêu chuẩn được đề cập ở trên là một phần của lớp EQ này. Bất cứ khi nào chúng tôi đang kiểm tra một đẳng thức bằng cách sử dụng bất kỳ loại nào được đề cập ở trên, chúng tôi thực sự đang thực hiện cuộc gọi đến lớp loại EQ

Trong ví dụ sau, chúng tôi đang sử dụng Loại EQ bên trong bằng thao tác "==" hoặc "/="

4
7

Nó sẽ mang lại đầu ra sau -

4
8

Thứ tự loại lớp

Ord is another interface class which gives us the functionality of ordering. All the types that we have used so far are a part of this Ord interface. Like EQ interface, Ord interface can be called using ">", "<", "<=", ">=", "compare".

Vui lòng tìm ví dụ bên dưới nơi chúng tôi đã sử dụng chức năng “so sánh” của Loại Loại này

4
9

Ở đây, trình biên dịch Haskell sẽ kiểm tra xem 4 có nhỏ hơn hoặc bằng 2 không. Vì không phải như vậy, mã sẽ tạo ra đầu ra sau -

Prelude> 15+(5*5)-40 
0

Trình diễn

Show có chức năng in đối số của nó dưới dạng Chuỗi. Bất kể đối số của nó là gì, nó luôn in kết quả dưới dạng Chuỗi. Trong ví dụ sau, chúng tôi sẽ in toàn bộ danh sách bằng giao diện này. "show" có thể được sử dụng để gọi giao diện này

Prelude> 15+(5*5)-40 
1

Nó sẽ tạo ra đầu ra sau trên bàn điều khiển. Ở đây, dấu ngoặc kép cho biết đó là giá trị kiểu Chuỗi

Prelude> 15+(5*5)-40 
2

Đọc

Giao diện Đọc thực hiện tương tự như Hiển thị, nhưng nó sẽ không in kết quả ở định dạng Chuỗi. Trong đoạn mã sau, chúng tôi đã sử dụng giao diện đọc để đọc một giá trị chuỗi và chuyển đổi giá trị đó thành giá trị Int

Prelude> 15+(5*5)-40 
3

Ở đây, chúng tôi đang chuyển một biến Chuỗi ("12") sang phương thức readInt, phương thức này sẽ trả về 12 (một giá trị Int) sau khi chuyển đổi. Đây là đầu ra của nó -

Prelude> 15+(5*5)-40 
4

liệt kê

Enum là một loại lớp Loại khác cho phép chức năng tuần tự hoặc theo thứ tự trong Haskell. Lớp Loại này có thể được truy cập bằng các lệnh như Succ, Pred, Bool, Char, v.v.

Đoạn mã sau chỉ ra cách tìm giá trị kế tiếp của 12

Prelude> 15+(5*5)-40 
5

Nó sẽ tạo ra đầu ra sau -

Prelude> 15+(5*5)-40 
6

giới hạn

Tất cả các loại có giới hạn trên và dưới đều thuộc Loại Loại này. Ví dụ: dữ liệu kiểu Int có giới hạn tối đa là "9223372036854775807" và giới hạn tối thiểu là "-9223372036854775808"

Đoạn mã sau cho thấy cách Haskell xác định giới hạn tối đa và tối thiểu của kiểu Int

Prelude> 15+(5*5)-40 
7

Nó sẽ tạo ra đầu ra sau -

Prelude> 15+(5*5)-40 
8

Bây giờ, hãy thử tìm giới hạn tối đa và tối thiểu của các loại Char, Float và Bool

số

Lớp loại này được sử dụng cho các hoạt động số. Các kiểu như Int, Integer, Float và Double thuộc lớp Type này. Hãy xem đoạn mã sau -

Prelude> 15+(5*5)-40 
9

Nó sẽ tạo ra đầu ra sau -

0
0

tích phân

Tích phân có thể được coi là một lớp con của Lớp loại Num. Lớp Num Type chứa tất cả các loại số, trong khi lớp Integral chỉ được sử dụng cho các số nguyên. Int và Integer là các kiểu trong lớp Loại này

Nổi

Giống như Integral, Floating cũng là một phần của lớp Num Type, nhưng nó chỉ chứa các số dấu phẩy động. Do đó, Float và Double thuộc lớp loại này

Loại tùy chỉnh

Giống như bất kỳ ngôn ngữ lập trình nào khác, Haskell cho phép các nhà phát triển xác định các loại do người dùng xác định. Trong ví dụ sau, chúng tôi sẽ tạo một loại do người dùng xác định và sử dụng nó

0
1

Ở đây, chúng tôi đã tạo một loại mới gọi là Khu vực. Tiếp theo, chúng tôi đang sử dụng loại này để tính diện tích hình tròn. Trong ví dụ trên, "bề mặt" là một hàm lấy Diện tích làm đầu vào và tạo Float làm đầu ra

Hãy nhớ rằng "dữ liệu" là một từ khóa ở đây và tất cả các loại do người dùng xác định trong Haskell luôn bắt đầu bằng chữ in hoa

Nó sẽ tạo ra đầu ra sau -

0
2

Hàm đóng vai trò chính trong Haskell, vì nó là ngôn ngữ lập trình hàm. Giống như các ngôn ngữ khác, Haskell có định nghĩa và khai báo hàm riêng

  • Khai báo hàm bao gồm tên hàm và danh sách đối số của nó cùng với đầu ra của nó

  • Định nghĩa hàm là nơi bạn thực sự định nghĩa một hàm

Hãy để chúng tôi lấy một ví dụ nhỏ về chức năng thêm để hiểu khái niệm này một cách chi tiết

0
3

Ở đây, chúng ta đã khai báo hàm của mình ở dòng đầu tiên và ở dòng thứ hai, chúng ta đã viết hàm thực tế sẽ nhận hai đối số và tạo ra một đầu ra kiểu số nguyên

Giống như hầu hết các ngôn ngữ khác, Haskell bắt đầu biên dịch mã từ phương thức chính. Mã của chúng tôi sẽ tạo đầu ra sau -

0
4

Khớp mẫu

Khớp mẫu là quá trình khớp loại biểu thức cụ thể. Nó không là gì ngoài một kỹ thuật để đơn giản hóa mã của bạn. Kỹ thuật này có thể được triển khai vào bất kỳ loại lớp Loại nào. If-Else có thể được sử dụng như một tùy chọn thay thế của khớp mẫu

Khớp mẫu có thể được coi là một biến thể của đa hình động trong thời gian chạy, các phương thức khác nhau có thể được thực thi tùy thuộc vào danh sách đối số của chúng

Hãy xem khối mã sau. Ở đây chúng tôi đã sử dụng kỹ thuật Khớp mẫu để tính giai thừa của một số

0
5

Chúng ta đều biết cách tính giai thừa của một số. Trình biên dịch sẽ bắt đầu tìm kiếm một hàm gọi là "thực tế" với một đối số. Nếu đối số không bằng 0, thì số đó sẽ tiếp tục gọi cùng một hàm với giá trị nhỏ hơn 1 so với đối số thực tế

Khi mẫu của đối số khớp chính xác với 0, nó sẽ gọi mẫu của chúng ta là "thực tế 0 = 1". Mã của chúng tôi sẽ tạo ra đầu ra sau -

0
6

bảo vệ

Guards là một khái niệm rất giống với khớp mẫu. Trong khớp mẫu, chúng tôi thường khớp một hoặc nhiều biểu thức, nhưng chúng tôi sử dụng bộ bảo vệ để kiểm tra một số thuộc tính của biểu thức

Mặc dù nên sử dụng đối sánh mẫu trên các bộ bảo vệ, nhưng từ quan điểm của nhà phát triển, các bộ bảo vệ dễ đọc và đơn giản hơn. Đối với những người dùng lần đầu, các bộ bảo vệ có thể trông rất giống với các câu lệnh If-Else, nhưng chúng khác về mặt chức năng

Trong đoạn mã sau, chúng tôi đã sửa đổi chương trình giai thừa của mình bằng cách sử dụng khái niệm lính canh

0
7

Ở đây, chúng tôi đã tuyên bố hai lính canh, cách nhau bởi ". " và gọi hàm fact từ main. Bên trong, trình biên dịch sẽ hoạt động theo cách tương tự như trong trường hợp khớp mẫu để tạo ra đầu ra sau -

0
6

Mệnh đề ở đâu

Đâu là từ khóa hoặc chức năng sẵn có có thể được sử dụng trong thời gian chạy để tạo đầu ra mong muốn. Nó có thể rất hữu ích khi tính toán chức năng trở nên phức tạp

Xem xét một kịch bản trong đó đầu vào của bạn là một biểu thức phức tạp với nhiều tham số. Trong những trường hợp như vậy, bạn có thể chia toàn bộ biểu thức thành các phần nhỏ bằng cách sử dụng mệnh đề "where"

Trong ví dụ sau, chúng ta đang sử dụng một biểu thức toán học phức tạp. Chúng tôi sẽ chỉ cho bạn cách tìm nghiệm của phương trình đa thức [x^2 - 8x + 6] bằng Haskell

0
9

Lưu ý độ phức tạp của biểu thức của chúng tôi để tính nghiệm của hàm đa thức đã cho. Nó khá phức tạp. Do đó, chúng tôi đang phá vỡ biểu thức bằng cách sử dụng mệnh đề where. Đoạn mã trên sẽ tạo ra đầu ra sau -

Prelude> :t "a" 
0

Hàm đệ quy

Đệ quy là tình huống mà một hàm gọi chính nó lặp đi lặp lại. Haskell không cung cấp bất kỳ cơ sở lặp lại bất kỳ biểu thức nào nhiều lần. Thay vào đó, Haskell muốn bạn chia toàn bộ chức năng của mình thành một tập hợp các chức năng khác nhau và sử dụng kỹ thuật đệ quy để triển khai chức năng của bạn

Chúng ta hãy xem xét lại ví dụ đối sánh mẫu của chúng ta, trong đó chúng ta đã tính giai thừa của một số. Tìm giai thừa của một số là trường hợp điển hình của việc sử dụng Đệ quy. Tại đây, bạn có thể hỏi "Khớp mẫu khác với đệ quy như thế nào?" . Khớp mẫu hoạt động khi thiết lập ràng buộc đầu cuối, trong khi đệ quy là một lệnh gọi hàm

Trong ví dụ sau, chúng tôi đã sử dụng cả so khớp mẫu và đệ quy để tính giai thừa của 5

Prelude> :t "a" 
1

Nó sẽ tạo ra đầu ra sau -

0
6

Hàm bậc cao hơn

Cho đến bây giờ, những gì chúng ta đã thấy là các hàm Haskell lấy một loại làm đầu vào và tạo ra một loại khác làm đầu ra, điều này khá giống với các ngôn ngữ mệnh lệnh khác. Hàm bậc cao hơn là một tính năng độc đáo của Haskell nơi bạn có thể sử dụng một hàm làm đối số đầu vào hoặc đầu ra

Mặc dù đó là một khái niệm ảo, nhưng trong các chương trình trong thế giới thực, mọi chức năng mà chúng tôi xác định trong Haskell đều sử dụng cơ chế bậc cao hơn để cung cấp đầu ra. Nếu bạn có cơ hội xem xét chức năng thư viện của Haskell, thì bạn sẽ thấy rằng hầu hết các chức năng thư viện đã được viết theo trình tự cao hơn

Hãy để chúng tôi lấy một ví dụ trong đó chúng tôi sẽ nhập bản đồ chức năng bậc cao hơn sẵn có và sử dụng bản đồ tương tự để triển khai một hàm bậc cao khác theo lựa chọn của chúng tôi

Prelude> :t "a" 
3

Trong ví dụ trên, chúng ta đã sử dụng hàm toUpper của Type Class Char để chuyển đổi đầu vào của chúng ta thành chữ hoa. Ở đây, phương thức "bản đồ" đang lấy một hàm làm đối số và trả về đầu ra được yêu cầu. Đây là đầu ra của nó -

Prelude> :t "a" 
4

Biểu thức Lambda

Đôi khi chúng ta phải viết một chức năng sẽ chỉ được sử dụng một lần, trong suốt vòng đời của một ứng dụng. Để đối phó với loại tình huống này, các nhà phát triển Haskell sử dụng một khối ẩn danh khác được gọi là biểu thức lambda hoặc hàm lambda

Hàm không có định nghĩa được gọi là hàm lambda. Hàm lambda được biểu thị bằng ký tự "\". Hãy để chúng tôi lấy ví dụ sau, nơi chúng tôi sẽ tăng giá trị đầu vào lên 1 mà không tạo bất kỳ chức năng nào

Prelude> :t "a" 
5

Ở đây, chúng tôi đã tạo một chức năng ẩn danh không có tên. Nó lấy số nguyên 4 làm đối số và in giá trị đầu ra. Về cơ bản, chúng tôi đang vận hành một chức năng mà thậm chí không khai báo nó đúng cách. Đó là vẻ đẹp của biểu thức lambda

Biểu thức lambda của chúng tôi sẽ tạo ra đầu ra sau -

Prelude> :t "a" 
6

Cho đến bây giờ, chúng ta đã thảo luận về nhiều loại hàm Haskell và sử dụng các cách khác nhau để gọi các hàm đó. Trong chương này, chúng ta sẽ tìm hiểu về một số hàm cơ bản có thể dễ dàng sử dụng trong Haskell mà không cần nhập bất kỳ lớp Type đặc biệt nào. Hầu hết các hàm này là một phần của các hàm bậc cao khác

chức năng đầu

Chức năng đầu hoạt động trên Danh sách. Nó trả về đối số đầu tiên đầu tiên về cơ bản là một danh sách. Trong ví dụ sau, chúng tôi đang chuyển một danh sách có 10 giá trị và chúng tôi đang tạo phần tử đầu tiên của danh sách đó bằng hàm head

Prelude> :t "a" 
7

Nó sẽ tạo ra đầu ra sau -

Prelude> :t "a" 
8

chức năng đuôi

Đuôi là chức năng bổ sung cho chức năng đầu. Nó lấy một danh sách làm đầu vào và tạo ra toàn bộ danh sách không có phần đầu. Điều đó có nghĩa là, hàm tail trả về toàn bộ danh sách không có phần tử đầu tiên. Hãy xem ví dụ sau -

Prelude> :t "a" 
9

Nó sẽ tạo ra đầu ra sau -

"a" :: [Char] 
0

Chức năng cuối cùng

Như tên gợi ý, nó mang lại phần tử cuối cùng của danh sách được cung cấp làm đầu vào. Kiểm tra ví dụ sau

"a" :: [Char] 
1

Nó sẽ tạo ra đầu ra sau -

"a" :: [Char] 
2

Chức năng khởi tạo

Init hoạt động hoàn toàn ngược lại với hàm tail. Nó lấy một danh sách làm đối số và trả về toàn bộ danh sách mà không có mục cuối cùng

"a" :: [Char] 
3

Bây giờ, hãy quan sát đầu ra của nó -

"a" :: [Char] 
4

Chức năng Null

Null là hàm kiểm tra Boolean hoạt động trên Chuỗi và chỉ trả về True khi danh sách đã cho trống, nếu không, nó trả về Sai. Đoạn mã sau kiểm tra xem danh sách được cung cấp có trống hay không

"a" :: [Char] 
5

Nó sẽ tạo ra đầu ra sau -

"a" :: [Char] 
6

Chức năng đảo ngược

Nó hoạt động trên đầu vào Chuỗi và chuyển đổi toàn bộ đầu vào thành thứ tự ngược lại và kết quả là đưa ra một đầu ra. Dưới đây là cơ sở mã cho chức năng này

"a" :: [Char] 
7

Nó sẽ tạo ra đầu ra sau -

"a" :: [Char] 
8

Hàm chiều dài

Hàm này được sử dụng để tính toán độ dài của danh sách được cung cấp dưới dạng đối số. Hãy xem ví dụ sau -

"a" :: [Char] 
9

Chúng tôi có 10 phần tử trong danh sách của mình, do đó mã của chúng tôi sẽ mang lại 10 phần tử làm đầu ra

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 
0

thực hiện chức năng

Hàm Take dùng để tạo một chuỗi con từ một chuỗi khác. Đoạn mã sau cho thấy cách bạn có thể sử dụng hàm take trong Haskell −

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 
1

Mã này tạo ra một chuỗi con chứa 5 phần tử từ danh sách được cung cấp -

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 
2

Chức năng thả

Hàm này cũng được sử dụng để tạo chuỗi con. Nó có chức năng ngược lại với hàm take. Nhìn vào đoạn mã sau -

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 
3

Mã loại bỏ 5 phần tử đầu tiên khỏi danh sách được cung cấp và in 5 phần tử còn lại. Nó sẽ tạo ra đầu ra sau -

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 
4

Chức năng tối đa

Hàm này được sử dụng để tìm phần tử có giá trị lớn nhất từ ​​danh sách được cung cấp. Hãy để chúng tôi xem cách sử dụng nó trong thực tế -

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 
5

Đoạn mã trên sẽ tạo đầu ra sau -

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 
6

Chức năng tối thiểu

Hàm này được sử dụng để tìm phần tử có giá trị nhỏ nhất từ ​​danh sách được cung cấp. Nó chỉ là đối diện của chức năng tối đa

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 
7

Đầu ra của đoạn mã trên là -

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 
8

Hàm tính tổng

Như tên gợi ý, hàm này trả về tổng của tất cả các phần tử có trong danh sách được cung cấp. Đoạn mã sau lấy danh sách 5 phần tử và trả về tổng của chúng làm đầu ra

Prelude> :t a 
:1:1: Not in scope: 'a'  

Prelude> a 
:4:1: Not in scope: 'a' 
9

Nó sẽ tạo ra đầu ra sau -

Hello World 
00

chức năng sản phẩm

Bạn có thể sử dụng hàm này để nhân tất cả các phần tử trong danh sách và in giá trị của nó

Hello World 
01

Mã của chúng tôi sẽ tạo ra đầu ra sau -

Hello World 
02

Chức năng yếu tố

Chức năng này được sử dụng để kiểm tra xem danh sách được cung cấp có chứa một phần tử cụ thể hay không. Theo đó, nó sẽ trả về giá trị true hoặc false

Đoạn mã sau kiểm tra xem danh sách các phần tử được cung cấp có chứa giá trị 786 không

Hello World 
03

Nó sẽ tạo ra đầu ra sau -

Hello World 
04

Sử dụng cùng một mã để kiểm tra xem danh sách được cung cấp có chứa giá trị 1785 hay không

Thành phần chức năng là quá trình sử dụng đầu ra của một chức năng làm đầu vào của một chức năng khác. Sẽ tốt hơn nếu chúng ta học toán đằng sau thành phần. Trong toán học, thành phần được ký hiệu là f{g(x)} trong đó g() là một hàm và đầu ra của nó được sử dụng làm đầu vào của một hàm khác, nghĩa là f()

Thành phần chức năng có thể được thực hiện bằng cách sử dụng hai chức năng bất kỳ, miễn là loại đầu ra của một chức năng phù hợp với loại đầu vào của chức năng thứ hai. Chúng tôi sử dụng toán tử dấu chấm (. ) để thực hiện thành phần chức năng trong Haskell

Hãy xem mã ví dụ sau. Ở đây, chúng tôi đã sử dụng thành phần chức năng để tính toán xem một số đầu vào là chẵn hay lẻ

Hello World 
05

Ở đây, trong chức năng chính, chúng tôi đang gọi đồng thời hai chức năng, noto và thậm chí. Trình biên dịch trước tiên sẽ gọi hàm "eveno()" với 16 làm đối số. Sau đó, trình biên dịch sẽ sử dụng đầu ra của phương thức eveno làm đầu vào của phương thức noto()

Đầu ra của nó sẽ như sau -

Hello World 
06

Vì chúng tôi đang cung cấp số 16 làm đầu vào (là số chẵn), nên hàm eveno() trả về true, trở thành đầu vào cho hàm noto() và trả về đầu ra. "Đây là số chẵn"

Nếu bạn đã từng làm việc với Java, thì bạn sẽ biết tất cả các lớp được liên kết với nhau như thế nào trong một thư mục có tên là gói. Tương tự, Haskell có thể được coi là một tập hợp các mô-đun

Haskell là một ngôn ngữ chức năng và mọi thứ được biểu thị dưới dạng một biểu thức, do đó, Mô-đun có thể được gọi là một tập hợp các loại chức năng tương tự hoặc có liên quan

Bạn có thể nhập một hàm từ mô-đun này sang mô-đun khác. Tất cả các câu lệnh "nhập" phải xuất hiện trước khi bạn bắt đầu xác định các chức năng khác. Trong chương này, chúng ta sẽ tìm hiểu các tính năng khác nhau của các mô-đun Haskell

Mô-đun danh sách

Danh sách cung cấp một số hàm tuyệt vời để làm việc với dữ liệu kiểu danh sách. Khi bạn nhập mô-đun Danh sách, bạn có thể tùy ý sử dụng nhiều chức năng

Trong ví dụ sau, chúng tôi đã sử dụng một số chức năng quan trọng có sẵn trong mô-đun Danh sách

Hello World 
07

Ở đây, chúng ta có nhiều hàm mà không cần định nghĩa chúng. Đó là bởi vì các chức năng này có sẵn trong mô-đun Danh sách. Sau khi nhập mô-đun Danh sách, trình biên dịch Haskell đã cung cấp tất cả các chức năng này trong không gian tên chung. Do đó, chúng ta có thể sử dụng các chức năng này

Mã của chúng tôi sẽ mang lại đầu ra sau -

Hello World 
08

Mô-đun Char

Mô-đun Char có nhiều chức năng được xác định trước để hoạt động với loại Ký tự. Hãy xem khối mã sau đây -

Hello World 
09

Ở đây, các hàm toUpper và toLower đã được xác định bên trong mô-đun Char. Nó sẽ tạo ra đầu ra sau -

Hello World 
10

mô-đun bản đồ

Bản đồ là loại dữ liệu loại cặp giá trị gia tăng chưa được sắp xếp. Nó là một mô-đun được sử dụng rộng rãi với nhiều chức năng hữu ích. Ví dụ sau đây cho thấy cách bạn có thể sử dụng chức năng được xác định trước có sẵn trong mô-đun Bản đồ

Hello World 
11

Nó sẽ tạo ra đầu ra sau -

Hello World 
12

Đặt mô-đun

Mô-đun Set có một số hàm được xác định trước rất hữu ích để thao tác dữ liệu toán học. Một tập hợp được triển khai dưới dạng cây nhị phân, vì vậy tất cả các phần tử trong một tập hợp phải là duy nhất

Hãy xem mã ví dụ sau

Hello World 
13

Ở đây, chúng tôi đang sửa đổi Chuỗi thành Tập hợp. Nó sẽ tạo ra đầu ra sau. Quan sát rằng bộ đầu ra không có ký tự lặp lại

Hello World 
14

Mô-đun tùy chỉnh

Hãy xem cách chúng ta có thể tạo một mô-đun tùy chỉnh có thể được gọi ở các chương trình khác. Để triển khai mô-đun tùy chỉnh này, chúng tôi sẽ tạo một tệp riêng có tên "tùy chỉnh. hs" cùng với "chính. hs"

Hãy để chúng tôi tạo mô-đun tùy chỉnh và xác định một số chức năng trong đó

tập quán. hs

Hello World 
15

Mô-đun tùy chỉnh của chúng tôi đã sẵn sàng. Bây giờ, chúng ta hãy nhập nó vào một chương trình

chủ yếu. hs

Hello World 
16

Mã của chúng tôi sẽ tạo đầu ra sau -

Hello World 
17

Hàm showEven trả về True, vì "4" là số chẵn. Hàm showBoolean trả về "1" là hàm Boolean mà chúng ta truyền vào hàm là "True"

Tất cả các ví dụ mà chúng ta đã thảo luận cho đến nay là tĩnh trong tự nhiên. Trong chương này, chúng ta sẽ học cách giao tiếp động với người dùng. Chúng ta sẽ tìm hiểu các kỹ thuật nhập và xuất khác nhau được sử dụng trong Haskell

Tệp và luồng

Cho đến nay, chúng tôi đã mã hóa cứng tất cả các đầu vào trong chính chương trình. Chúng tôi đã lấy đầu vào từ các biến tĩnh. Bây giờ, chúng ta hãy tìm hiểu cách đọc và ghi từ một tệp bên ngoài

Hãy để chúng tôi tạo một tệp và đặt tên là "abc. txt". Tiếp theo, nhập các dòng sau vào tệp văn bản này. "Chào mừng đến với Tutorialspoint. Tại đây, bạn sẽ có được nguồn tài nguyên tốt nhất để học Haskell. "

Tiếp theo, chúng ta sẽ viết đoạn mã sau sẽ hiển thị nội dung của tệp này trên bàn điều khiển. Ở đây, chúng tôi đang sử dụng hàm readFile() để đọc tệp cho đến khi tìm thấy ký tự EOF

Hello World 
18

Đoạn mã trên sẽ đọc tệp "abc. txt" dưới dạng Chuỗi cho đến khi gặp bất kỳ ký tự Cuối tệp nào. Đoạn mã này sẽ tạo ra đầu ra sau

Hello World 
19

Quan sát rằng bất cứ thứ gì nó đang in trên thiết bị đầu cuối đều được ghi trong tệp đó

Đối số dòng lệnh

Haskell cũng cung cấp phương tiện để vận hành một tệp thông qua dấu nhắc lệnh. Hãy để chúng tôi quay lại thiết bị đầu cuối của mình và gõ "ghci". Sau đó, gõ tập lệnh sau –

Hello World 
20

Ở đây, chúng tôi đã tạo một tệp văn bản có tên "abc. txt". Tiếp theo, chúng tôi đã chèn một câu lệnh vào tệp bằng cách sử dụng lệnh writeFile. Cuối cùng, chúng ta đã sử dụng lệnh readFile để in nội dung của tệp trên bàn điều khiển. Mã của chúng tôi sẽ tạo ra đầu ra sau -

Hello World 
21

ngoại lệ

Một ngoại lệ có thể được coi là một lỗi trong mã. Đó là tình huống mà trình biên dịch không nhận được đầu ra như mong đợi khi chạy. Giống như bất kỳ ngôn ngữ lập trình tốt nào khác, Haskell cung cấp cách triển khai xử lý ngoại lệ

Nếu bạn đã quen thuộc với Java, thì bạn có thể biết khối Try-Catch nơi chúng ta thường đưa ra một lỗi và bắt lỗi tương tự trong khối catch. Trong Haskell, chúng ta cũng có chức năng bắt lỗi thời gian chạy tương tự

Định nghĩa chức năng của try trông giống như "thử. Ngoại lệ e => IO a -> IO (Hoặc e a)". Hãy xem mã ví dụ sau. Nó cho thấy cách bạn có thể nắm bắt ngoại lệ "Chia cho số không"

Hello World 
22

Trong ví dụ trên, chúng tôi đã sử dụng chức năng thử sẵn có của Control. Mô-đun ngoại lệ, do đó chúng tôi đang bắt ngoại lệ trước. Đoạn mã trên sẽ mang lại đầu ra bên dưới trong màn hình

Hello World 
23

Functor trong Haskell là một loại biểu diễn chức năng của các Loại khác nhau có thể được ánh xạ qua. Đó là một khái niệm cấp cao về thực hiện đa hình. Theo các nhà phát triển Haskell, tất cả các Loại như Danh sách, Bản đồ, Cây, v.v. là ví dụ của Haskell Functor

Functor là một lớp sẵn có với định nghĩa hàm như -

Hello World 
24

Theo định nghĩa này, chúng ta có thể kết luận rằng Functor là một hàm nhận một hàm, ví dụ, fmap() và trả về một hàm khác. Trong ví dụ trên, fmap() là một biểu diễn tổng quát của hàm map()

Trong ví dụ sau, chúng ta sẽ xem Haskell Functor hoạt động như thế nào

Hello World 
25

Ở đây, chúng tôi đã sử dụng cả map() và fmap() trên một danh sách cho phép trừ. Bạn có thể quan sát thấy rằng cả hai câu lệnh sẽ mang lại cùng một kết quả là danh sách chứa các phần tử [1,3,7,15]

Cả hai chức năng được gọi là một chức năng gọi là phép trừ () để mang lại kết quả

Hello World 
26

Sau đó, sự khác biệt giữa bản đồ và fmap là gì? . Functor cho phép chúng tôi triển khai thêm một số chức năng trong các loại dữ liệu khác nhau, như "chỉ" và "Không có gì"

Hello World 
27

Đoạn mã trên sẽ mang lại đầu ra sau trên thiết bị đầu cuối -

Hello World 
28

Functor ứng dụng

Một Functor ứng dụng là một Functor bình thường với một số tính năng bổ sung được cung cấp bởi Lớp loại ứng dụng

Using Functor, we usually map an existing function with another function defined inside it. But there is no any way to map a function which is defined inside a Functor with another Functor. That is why we have another facility called Applicative Functor. This facility of mapping is implemented by Applicative Type class defined under the Control module. This class gives us only two methods to work with: one is pure and the other one is <*>.

Sau đây là định nghĩa lớp của Functor Ứng dụng

Hello World 
29

According to the implementation, we can map another Functor using two methods: "Pure" and "<*>". The "Pure" method should take a value of any type and it will always return an Applicative Functor of that value.

Ví dụ sau đây cho thấy cách thức hoạt động của Applicative Functor -

Hello World 
30

Ở đây, chúng tôi đã triển khai các hàm ứng dụng trong lệnh gọi hàm của hàm f1. Chương trình của chúng tôi sẽ mang lại đầu ra sau

Hello World 
31

đơn sắc

Chúng ta đều biết Haskell định nghĩa mọi thứ ở dạng hàm. Trong các hàm, chúng ta có các tùy chọn để lấy đầu vào làm đầu ra của hàm. Đây là những gì một Monoid là

Monoid là một tập hợp các hàm và toán tử trong đó đầu ra độc lập với đầu vào của nó. Hãy lấy một hàm (*) và một số nguyên (1). Bây giờ, bất kể đầu vào là gì, đầu ra của nó sẽ chỉ giữ nguyên một số. Tức là nếu nhân một số với 1 thì sẽ được chính số đó

Đây là một định nghĩa Type Class của monoid

Hello World 
32

Hãy xem ví dụ sau để hiểu công dụng của Monoid trong Haskell

Hello World 
33

Mã của chúng tôi sẽ tạo ra đầu ra sau -

Hello World 
34

Ở đây, hàm "multi" nhân đầu vào với "1". Tương tự, hàm "add" thêm đầu vào bằng "0". Trong cả hai trường hợp, đầu ra sẽ giống như đầu vào. Do đó, các hàm {(*),1} và {(+),0} là những ví dụ hoàn hảo về đơn thức

Monads không là gì ngoài một loại Functor Ứng dụng với một số tính năng bổ sung. Đó là một lớp Loại chi phối ba quy tắc cơ bản được gọi là quy tắc đơn nguyên

Tất cả ba quy tắc đều được áp dụng nghiêm ngặt đối với khai báo Monad như sau -

Hello World 
35

Ba luật cơ bản được áp dụng cho khai báo Monad là -

  • Luật nhận dạng bên trái - Hàm trả về không thay đổi giá trị và nó sẽ không thay đổi bất cứ điều gì trong Monad. Nó có thể được diễn đạt là "return >=> mf = mf"

  • Luật nhận dạng đúng - Hàm trả về không thay đổi giá trị và nó sẽ không thay đổi bất cứ điều gì trong Monad. Nó có thể được diễn đạt là "mf >=> return = mf"

  • Tính kết hợp - Theo luật này, cả Functors và Monad instance phải hoạt động theo cùng một cách. Nó có thể được biểu thị bằng toán học là "( f >==>g) >=> h =f >= >(g >=h)"

Hai luật đầu tiên lặp lại cùng một điểm, tôi. e. , trả về phải có hành vi nhận dạng ở cả hai phía của toán tử liên kết

Chúng tôi đã sử dụng rất nhiều Monad trong các ví dụ trước của chúng tôi mà không nhận ra rằng chúng là Monad. Hãy xem xét ví dụ sau khi chúng tôi đang sử dụng Danh sách Monad để tạo một danh sách cụ thể

Hello World 
36

Mã này sẽ tạo ra đầu ra sau -

Hello World 
37

Các dây kéo trong Haskell về cơ bản là các con trỏ trỏ đến một số vị trí cụ thể của cấu trúc dữ liệu, chẳng hạn như cây

Chúng ta hãy xem xét một cây có 5 phần tử [45,7,55,120,56] có thể được biểu diễn dưới dạng cây nhị phân hoàn hảo. Nếu tôi muốn cập nhật phần tử cuối cùng của danh sách này, thì tôi cần duyệt qua tất cả các phần tử để đến phần tử cuối cùng trước khi cập nhật nó. Đúng?

Nhưng, điều gì sẽ xảy ra nếu chúng ta có thể xây dựng cây của mình theo cách sao cho một cây có N phần tử là một tập hợp của [(N-1),N]. Sau đó, chúng ta không cần duyệt qua tất cả các phần tử (N-1) không mong muốn. Chúng tôi có thể cập nhật trực tiếp phần tử thứ N. Đây chính xác là khái niệm về Zipper. Nó tập trung hoặc trỏ đến một vị trí cụ thể của cây nơi chúng ta có thể cập nhật giá trị đó mà không cần duyệt qua toàn bộ cây

Trong ví dụ sau, chúng tôi đã triển khai khái niệm Zipper trong Danh sách. Theo cách tương tự, người ta có thể triển khai Zipper trong cấu trúc dữ liệu cây hoặc tệp

Hello World 
38

Khi bạn biên dịch và thực thi chương trình trên, nó sẽ tạo ra đầu ra sau -

Hello World 
39

Ở đây chúng tôi đang tập trung vào một phần tử của toàn bộ chuỗi trong khi tiến hoặc lùi