The post Haskell – Functor appeared first on Dongthoigian.net.
]]>class Functor f where
fmap :: (a -> b) -> f a -> f b
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, chẳng hạn như, 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 bản đồ hàm () . Trong ví dụ sau, chúng ta sẽ xem Haskell Functor hoạt động như thế nào.
main = do
print(map (subtract 1) [2,4,8,16])
print(fmap (subtract 1) [2,4,8,16])
Ở đây, chúng tôi đã sử dụng cả map () và fmap () trên một danh sách cho một phép toán trừ. Bạn có thể 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 hàm được gọi là một hàm khác được gọi là subtract () để mang lại kết quả.
[1,3,7,15][1,3,7,15]
Sau đó, sự khác biệt giữa map và fmap là gì? Sự khác biệt nằm ở cách sử dụng của chúng. Functor cho phép chúng tôi triển khai thêm một số hàm chức năng trong các kiểu dữ liệu khác nhau, như “just” và “Nothing”.
main = do
print (fmap (+7)(Just 10))
print (fmap (+7) Nothing)
Đoạn mã trên sẽ mang lại kết quả đầu ra sau trên thiết bị đầu cuối:
Just 17
Nothing
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.
Sử dụng Functor, chúng tôi thường ánh xạ một hàm hiện có với một hàm khác được định nghĩa bên trong nó. Nhưng không có bất kỳ cách nào để ánh xạ một hàm được định nghĩa bên trong Functor với Functor khác. Đó là lý do tại sao chúng tôi có một cơ sở khác được gọi là Application Functor . Cơ sở ánh xạ này được thực hiện bởi lớp Loại ứng dụng được xác định trong mô-đun Điều khiển . Lớp này chỉ cung cấp cho chúng ta hai phương thức để làm việc: một là thuần túy và một là <*> . Sau đây là định nghĩa lớp của Ứng dụng Functor
class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
Theo cách triển khai, chúng ta có thể ánh xạ Functor khác bằng hai phương pháp: “Pure” và “<*>” . Phương thức “Pure” phải nhận một giá trị thuộc bất kỳ loại nào và nó sẽ luôn trả về một Functor Ứng dụng có giá trị đó.
Ví dụ sau đây cho thấy cách một Functor Ứng dụng hoạt động:
import Control.Applicative
f1:: Int -> Int -> Int
f1 x y = 2*x+y
main = do
print(show $ f1 <$> (Just 1) <*> (Just 2) )
Ở đây, chúng ta đã triển khai các hàm ứng dụng trong lời gọi hàm của hàm f1 . Chương trình của chúng tôi sẽ mang lại kết quả sau.
"Just 4"
Chúng ta đều biết Haskell định nghĩa mọi thứ dưới dạng các hàm. Trong các hàm, chúng ta có các tùy chọn để lấy đầu vào của mình làm đầu ra của hàm. Đây là những gì một Monoid là.
Một monoid là một tập hợp các chức năng và các nhà khai thác mà đầu ra không phụ thuộc vào đầ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 có thể là gì, đầu ra của nó sẽ chỉ giữ nguyên một con số. Nghĩa là, nếu bạn nhân một số với 1, bạn sẽ nhận được cùng một số.
Đây là định nghĩa Loại Class của monoid.
class Monoid m where
mempty :: m
mappend :: m -> m -> m
mconcat :: [m] -> m
mconcat = foldr mappend mempty
Hãy xem ví dụ sau để hiểu việc sử dụng Monoid trong Haskell
multi:: Int->Int
multi x = x * 1
add :: Int->Int
add x = x + 0
main = do
print(multi 9)
print (add 7)
Mã của chúng tôi sẽ tạo ra kết quả sau: 9 7
Ở đâ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 với đầu vào. Do đó, các hàm {(*), 1} và {(+), 0} là những ví dụ hoàn hảo về đơn chất.
Các đơn nguyên 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. Nó là một lớp Loại điều chỉnh ba quy tắc cơ bản được gọi là quy tắc đơn nguyên .
Tất cả ba quy tắc này đều có thể áp dụng nghiêm ngặt cho một tuyên bố Monad như sau:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
x >> y = x >>= \_ -> y
fail :: String -> m a
fail msg = error msg
Ba luật cơ bản có thể áp dụng cho tuyên bố Monad là:
Hai luật đầu tiên lặp lại cùng một điểm, tức là, một trả về phải có hành vi nhận dạng ở cả hai phía của toán tử ràng buộc . Chúng tôi đã sử dụng rất nhiều Đơn nguyên trong các ví dụ trước đây của chúng tôi mà không nhận ra rằng chúng là Đơn nguyên. Hãy xem xét ví dụ sau, nơi chúng tôi đang sử dụng Đơn nguyên danh sách để tạo một danh sách cụ thể
main = do
print([1..10] >>= (\x -> if odd x then [x*2] else []))
Mã này sẽ tạo ra kết quả sau: [2,6,10,14,18]
Các khóa 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 như một 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 xem qua tất cả các phần tử để tiếp cận phần tử cuối cùng trước khi cập nhật nó. Bên phải?
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 mà một cây có N phần tử là tập hợp của [(N-1), N] . Sau đó, chúng ta không cần phải 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 Zipper. Nó tập trung hoặc trỏ đến một vị trí cụ thể của một cây mà chúng ta có thể cập nhật giá trị đó mà không cần đi ngang qua toàn bộ cây. Trong ví dụ sau, chúng tôi đã triển khai khái niệm Zipper trong một 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 dạng cây hoặc tệp .
data List a = Empty | Cons a (List a) deriving (Show, Read, Eq, Ord)
type Zipper_List a = ([a],[a])
go_Forward :: Zipper_List a -> Zipper_List a
go_Forward (x:xs, bs) = (xs, x:bs)
go_Back :: Zipper_List a -> Zipper_List a
go_Back (xs, b:bs) = (b:xs, bs)
main = do
let list_Ex = [1,2,3,4]
print(go_Forward (list_Ex,[]))
print(go_Back([4],[3,2,1]))
Khi bạn biên dịch và thực thi chương trình trên, nó sẽ tạo ra kết quả sau:
([2,3,4],[1])
([3,4],[2,1])
Ở đâ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 lên hoặc trong khi lùi lại.
The post Haskell – Functor appeared first on Dongthoigian.net.
]]>The post Haskell – Thành phần chức năng appeared first on Dongthoigian.net.
]]>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à kiểu đầu ra của một chức năng phù hợp với kiểu đầ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 (.) Để triển khai thành phần hàm trong Haskell. Hãy xem đoạn mã ví dụ sau. Ở đây, chúng tôi đã sử dụng thành phần hàm để tính toán xem một số đầu vào là chẵn hay lẻ
eveno :: Int -> Bool
noto :: Bool -> String
eveno x = if x `rem` 2 == 0
then True
else False
noto x = if x == True
then "This is an even Number"
else "This is an ODD number"
main = do
putStrLn "Example of Haskell Function composition"
print ((noto.eveno)(16))
Ở đây, trong hàm chính , chúng ta đang gọi đồng thời hai hàm, noto và eveno . Đầu tiên, trình biên dịch 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:
Example of Haskell Function composition
“This is an even Number”
Vì chúng ta đang cung cấp số 16 làm đầu vào (là một số chẵn), hàm eveno () trả về true , trở thành đầu vào cho hàm noto () và trả về đầu ra: “Đây là một số chẵn”.
Haskell - Mô-đun
Nếu bạn đã làm việc trên Java, thì bạn sẽ biết cách tất cả các lớp được liên kết vào một thư mục được gọi 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ột 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 chức năng từ một mô-đun này vào một mô-đun khác. Tất cả các câu lệnh “nhập” phải xuất hiện đầu tiên trước khi bạn bắt đầu xác định các hàm 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.
Danh sách cung cấp một số chức năng 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ó nhiều chức năng theo ý của mình. 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.
import Data.List
main = do
putStrLn("Different methods of List Module")
print(intersperse '.' "Tutorialspoint.com")
print(intercalate " " ["Lets","Start","with","Haskell"])
print(splitAt 7 "HaskellTutorial")
print (sort [8,5,3,2,1,6,4,2])
Ở đây, chúng ta có nhiều chức năng mà không cần xác định 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 làm cho tất cả các chức năng này khả dụng trong không gian tên chung. Do đó, chúng tôi có thể sử dụng các chức năng này. Mã của chúng tôi sẽ mang lại kết quả sau:
Different methods of List Module
"T.u.t.o.r.i.a.l.s.p.o.i.n.t...c.o.m"
"Lets Start with Haskell"
("Haskell","Tutorial")
[1,2,2,3,4,5,6,8]
Các Char mô-đun có rất nhiều chức năng được xác định trước để làm việc với các loại nhân vật. Hãy xem khối mã sau:
import Data.Char
main = do
putStrLn("Different methods of Char Module")
print(toUpper 'a')
print(words "Let us study tonight")
print(toLower 'A')
Ở đây, các chức năng toUpper và toLower đã được xác định bên trong mô-đun Char . Nó sẽ tạo ra kết quả sau:
Different methods of Char Module
'A'
["Let","us","study","tonight"]
'a'
Bản đồ là kiểu dữ liệu kiểu cặp giá trị gia tăng không đượ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 một chức năng được xác định trước có sẵn trong mô-đun Bản đồ.
import Data.Map (Map)
import qualified Data.Map as Map --required for GHCI
myMap :: Integer -> Map Integer [Integer]
myMap n = Map.fromList (map makePair [1..n])
where makePair x = (x, [x])
main = print(myMap 3)
Nó sẽ tạo ra kết quả sau:
fromList [(1,[1]),(2,[2]),(3,[3])]
Mô-đun Set có một số chức năng được xác định trước rất hữu ích để thao tác với dữ liệu toán học. Một tập hợp được thực hiện 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 đoạn mã ví dụ sau
import qualified Data.Set as Set
text1 = "Hey buddy"
text2 = "This tutorial is for Haskell"
main = do
let set1 = Set.fromList text1
set2 = Set.fromList text2
print(set1)
print(set2)
Ở đây, chúng tôi đang sửa đổi một Chuỗi thành một Tập hợp. Nó sẽ tạo ra kết quả sau. Quan sát rằng tập hợp đầu ra không có sự lặp lại của các ký tự
fromList " Hbdeuy"
fromList " HTaefhiklorstu"
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 “custom.hs” cùng với “main.hs” của chúng tôi .
Hãy để chúng tôi tạo mô-đun tùy chỉnh và xác định một vài chức năng trong đó.custom.hs
module Custom (
showEven,
showBoolean
) where
showEven:: Int-> Bool
showEven x = do
if x 'rem' 2 == 0
then True
else False
showBoolean :: Bool->Int
showBoolean c = do
if c == True
then 1
else 0
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.
import Custom
main = do
print(showEven 4)
print(showBoolean True)
Mã của chúng tôi sẽ tạo ra kết quả sau: True 1
Hàm showEven trả về giá trị True , vì “4” là số chẵn. Hàm showBoolean trả về “1” vì 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 đều có bản chất tĩnh. 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ẽ học các kỹ thuật đầu vào và đầu ra khác nhau được sử dụng trong Haskell.
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 bạn đến với Tutorialspoint. Tại đây, bạn sẽ nhận được tài nguyên tốt nhất để học Haskell.”
Tiếp theo, chúng ta sẽ viết đoạn mã sau để hiển thị nội dung của tệp này trên bảng điều khiển. Ở đây, chúng ta đang sử dụng hàm readFile () để đọc một tệp cho đến khi nó tìm thấy một ký tự EOF.
main = do
let file = "abc.txt"
contents <- readFile file
putStrLn contents
Đoạn mã trên sẽ đọc tệp “abc.txt” dưới dạng Chuỗi cho đến khi nó gặp bất kỳ ký tự Cuối tệp nào. Đoạn mã này sẽ tạo ra kết quả sau.
Welcome to Tutorialspoint
Here, you will get the best resource to learn Haskell.
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 đó.
Haskell cũng cung cấp cơ sở để 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 và nhập “ghci” . Sau đó, nhập nhóm lệnh sau:
let file = "abc.txt"
writeFile file "I am just experimenting here."
readFile file
Ở đâ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 trong tệp bằ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ảng điều khiển. Mã của chúng tôi sẽ tạo ra kết quả sau:
I am just experimenting here.
Một ngoại lệ có thể được coi là một lỗi trong mã. Đó là một tình huống mà trình biên dịch không nhận được đầu ra mong đợi trong thời gian 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 một cách để thực hiện 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 phát hiện ra một lỗi và bắt giống nhau trong khối catch . Trong Haskell, chúng ta cũng có chức năng tương tự để bắt lỗi thời gian chạy.
Định nghĩa hàm của try trông giống như “try :: Exception e => IO a -> IO (Either ea)”. Hãy xem đoạn mã ví dụ sau. Nó chỉ ra cách bạn có thể bắt được ngoại lệ “Chia cho 0”.
Ở đâ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 trong tệp bằ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ảng điều khiển. Mã của chúng tôi sẽ tạo ra kết quả sau:
I am just experimenting here.
Ngoại lệ
Một ngoại lệ có thể được coi là một lỗi trong mã. Đó là một tình huống mà trình biên dịch không nhận được đầu ra mong đợi trong thời gian 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 một cách để thực hiện 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 phát hiện ra một lỗi và bắt giống nhau trong khối catch . Trong Haskell, chúng ta cũng có chức năng tương tự để bắt lỗi thời gian chạy.
Định nghĩa hàm của try trông giống như "try :: Exception e => IO a -> IO (Either ea)". Hãy xem đoạn mã ví dụ sau. Nó chỉ ra cách bạn có thể bắt được ngoại lệ "Chia cho 0".
import Control.Exception
main = do
result <- try (evaluate (5 `div` 0)) :: IO (Either SomeException Int)
case result of
Left ex -> putStrLn $ "Caught exception: " ++ show ex
Right val -> putStrLn $ "The answer was: " ++ show val
Trong ví dụ trên, chúng tôi đã sử dụng hàm try có sẵn của mô-đun Control.Exception , do đó chúng tôi đang bắt trước ngoại lệ. Đoạn mã phía trên sẽ mang lại kết quả bên dưới trong màn hình.
Caught exception: divide by zero
The post Haskell – Thành phần chức năng appeared first on Dongthoigian.net.
]]>The post Haskell – Thêm về các chức năng appeared first on Dongthoigian.net.
]]>Chức năng Head hoạt động trên một Danh sách. Nó trả về đối số đầ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 cách sử dụng hàm head
main = do
let x = [1..10]
putStrLn "Our list is:"
print (x)
putStrLn "The first element of the list is:"
print (head x)
Nó sẽ tạo ra kết quả sau:
Our list is:
[1,2,3,4,5,6,7,8,9,10]
The first element of the list is:
1
Đuôi là chức năng bổ sung cho chức năng của đầu . Nó lấy một danh sách làm đầu vào và tạo ra toàn bộ danh sách mà không có phần đầu. Điều đó có nghĩa là, hàm tail trả về toàn bộ danh sách mà không có phần tử đầu tiên. Hãy xem ví dụ sau:
main = do
let x = [1..10]
putStrLn "Our list is:"
print (x)
putStrLn "The tail of our list is:"
print (tail x)
Nó sẽ tạo ra kết quả sau: Danh sách của chúng tôi là:
[1,2,3,4,5,6,7,8,9,10]
Phần cuối của danh sách của chúng tôi là:
[2,3,4,5,6,7,8,9,10]
Như tên cho thấy, 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.
main = do
let x = [1..10]
putStrLn "Our list is:"
print (x)
putStrLn "The last element of our list is:"
print (last x)
Nó sẽ tạo ra kết quả sau:
Our list is:
[1,2,3,4,5,6,7,8,9,10]
The last element of our list is:
10
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 nhập cuối cùng
main = do
let x = [1..10]
putStrLn "Our list is:"
print (x)
putStrLn "Our list without the last entry:"
print (init x)
Bây giờ, hãy quan sát đầu ra của nó –
Our list is:
[1,2,3,4,5,6,7,8,9,10]
Our list without the last entry:
[1,2,3,4,5,6,7,8,9]
Hàm Null Null Function
Null là một hàm kiểm tra Boolean hoạt động trên một Chuỗi và chỉ trả về True khi danh sách đã cho trống, nếu không, nó trả về False . Đoạn mã sau kiểm tra xem danh sách được cung cấp có trống hay không.
main = do
let x = [1..10]
putStrLn "Our list is:"
print (x)
putStrLn "Is our list empty?"
print (null x)
Nó sẽ tạo ra kết quả sau:
Our list is:
[1,2,3,4,5,6,7,8,9,10]
Is our list empty?
False
Nó hoạt động trên đầu vào Chuỗi và chuyển toàn bộ đầu vào thành thứ tự ngược lại và kết quả là một đầu ra. Dưới đây là cơ sở mã cho chức năng này.
main = do
let x = [1..10]
putStrLn "Our list is:"
print (x)
putStrLn "The list in Reverse Order is:"
print (reverse x)
Nó sẽ tạo ra kết quả sau: Danh sách của chúng tôi là:
Our list is:
[1,2,3,4,5,6,7,8,9,10]
The list in Reverse Order is:
[10,9,8,7,6,5,4,3,2,1]
Hàm này được sử dụng để tính toán độ dài của danh sách được đưa ra dưới dạng một đối số. Hãy xem ví dụ sau:
main = do
let x = [1..10]
putStrLn "Our list is:"
print (x)
putStrLn "The length of this list is:"
print (length x)
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ử như đầu ra.
Our list is:
[1,2,3,4,5,6,7,8,9,10]
The length of this list is:
10
Hàm Take được sử dụng để tạo một chuỗi con từ một Chuỗi khác. Đoạn mã sau đây cho thấy cách bạn có thể sử dụng hàm take trong Haskell:
main = print(take 5 ([1 .. 10]))
Mã tạo một chuỗi con chứa 5 phần tử từ danh sách được cung cấp –
[1,2,3,4,5]
Hàm này cũng được sử dụng để tạo một chuỗi con. Nó hoạt động như ngược lại với hàm lấy . Hãy xem đoạn mã sau:
main = print(drop 5 ([1 .. 10]))
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 kết quả sau:
[6,7,8,9,10]
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ế –
main = do
let x = [1,45,565,1245,02,2]
putStrLn "The maximum value element of the list is:"
print (maximum x)
Đoạn mã trên sẽ tạo ra kết quả sau:
The maximum value element of the list is:
1245
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ỉ đối lập với chức năng tối đa
main = do
let x = [1,45,565,1245,02,2]
putStrLn "The minimum value element of the list is:"
print (minimum x)
Đầu ra của đoạn mã trên là –
The minimum value element of the list is:
1
Như tên cho thấy, 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 kết của chúng dưới dạng đầu ra.
main = do
let x = [1..5]
putStrLn "Our list is:"
print (x)
putStrLn "The summation of the list elements is:"
print (sum x)
Nó sẽ tạo ra kết quả sau:
Danh sách của chúng tôi là:
[1,2,3,4,5]
Tổng của các phần tử danh sách là:
15
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ó.
Nó sẽ tạo ra kết quả sau:
Danh sách của chúng tôi là:
[1,2,3,4,5]
Tổng của các phần tử danh sách là:
15
Chức năng sản phẩm Product Function
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ó.
main = do
let x = [1..5]
putStrLn "Our list is:"
print (x)
putStrLn "The multiplication of the list elements is:"
print (product x)
Mã của chúng tôi sẽ tạo ra kết quả sau:
Our list is:
[1,2,3,4,5]
The multiplication of the list elements is:
120
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ó trả về 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 hay không.
main = do
let x = [1,45,155,1785]
putStrLn "Our list is:"
print (x)
putStrLn "Does it contain 786?"
print (elem 786 (x))
Nó sẽ tạo ra kết quả sau:
Our list is:
[1,45,155,1785]
Does it contain 786?
False Sử dụng mã tương tự để kiểm tra xem danh sách được cung cấp có chứa giá trị 1785 hay không.
Haskell – Thành phần chức năng (xem thêm)
The post Haskell – Thêm về các chức năng appeared first on Dongthoigian.net.
]]>The post Haskell – Chức năng appeared first on Dongthoigian.net.
]]>Chúng ta hãy lấy một ví dụ nhỏ về hàm add để hiểu chi tiết khái niệm này.
add :: Integer -> Integer -> Integer --function declaration
add x y = x + y --function definition
main = do
putStrLn "The addition of the two numbers is:"
print(add 2 5) --calling a function
Ở đâ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 của mình 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 ra kết quả sau:
The addition of the two numbers is:
7
Khớp mẫu là quá trình đối sánh 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 Type nào. If-Else có thể được sử dụng như một tùy chọn thay thế của đối sánh mẫu.
Đối sánh mẫu có thể được coi là một biến thể của đa hình động, trong đó tại 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 So khớp mẫu để tính giai thừa của một số.
fact :: Int -> Int
fact 0 = 1
fact n = n * fact ( n - 1 )
main = do
putStrLn "The factorial of 5 is:"
print (fact 5)
Tất cả 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 được gọi là “fact” 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 số ít hơn 1 so với đối số thực. 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à “fact 0 = 1”. Mã của chúng tôi sẽ tạo ra kết quả sau:
The factorial of 5 is:
120
Bảo vệ là một khái niệm rất giống với đối sánh mẫu. Trong đối sánh mẫu, chúng tôi thường so khớp một hoặc nhiều biểu thức, nhưng chúng tôi sử dụng bảo vệ để kiểm tra một số thuộc tính của một biểu thức.
Mặc dù nên sử dụng đối sánh mẫu thay vì bảo vệ , nhưng từ quan điểm của nhà phát triển, bảo vệ dễ đọc và đơn giản hơn. Đối với những người sử dụng lần đầu, bảo vệ có thể trông rất giống với câu lệnh If-Else, nhưng chúng khác nhau về 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 .
Lính canh
Bảo vệ là một khái niệm rất giống với đối sánh mẫu. Trong đối sánh mẫu, chúng tôi thường so khớp một hoặc nhiều biểu thức, nhưng chúng tôi sử dụng bảo vệ để kiểm tra một số thuộc tính của một biểu thức.
Mặc dù nên sử dụng đối sánh mẫu thay vì bảo vệ , nhưng từ quan điểm của nhà phát triển, bảo vệ dễ đọc và đơn giản hơn. Đối với những người sử dụng lần đầu, bảo vệ có thể trông rất giống với câu lệnh If-Else, nhưng chúng khác nhau về 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 .
fact :: Integer -> Integer
fact n | n == 0 = 1
| n /= 0 = n * fact (n-1)
main = do
putStrLn "The factorial of 5 is:"
print (fact 5)
Ở đây, chúng tôi đã khai báo 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 để mang lại kết quả sau:
The factorial of 5 is:
120
Đâu là một từ khóa hoặc hàm có sẵn có thể được sử dụng trong thời gian chạy để tạo ra kết quả mong muốn. Nó có thể rất hữu ích khi việc tính toán hàm trở nên phức tạp.
Hãy xem xét một tình huống 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 bạn có thể tìm nghiệm nguyên của phương trình đa thức [x ^ 2 – 8x + 6] bằng cách sử dụng Haskell.
roots :: (Float, Float, Float) -> (Float, Float)
roots (a,b,c) = (x1, x2) where
x1 = e + sqrt d / (2 * a)
x2 = e - sqrt d / (2 * a)
d = b * b - 4 * a * c
e = - b / (2 * a)
main = do
putStrLn "The roots of our Polynomial equation are:"
print (roots(1,-8,6))
Lưu ý mức độ phức tạp của biểu thức của chúng ta để tính các nghiệm nguyên 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 kết quả sau:
The roots of our Polynomial equation are:
(7.1622777,0.8377223)
Đệ quy là một 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 hơn một 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ụ về đối sánh mẫu của chúng ta, nơi chúng ta đã tính giai thừa của một số. Tìm giai thừa của một số là một trường hợp cổ điển của việc sử dụng Đệ quy. Ở đây, bạn có thể, “So khớp mẫu khác với đệ quy như thế nào?” Sự khác biệt giữa hai điều này nằm ở cách chúng được sử dụng. So 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ời gọi hàm.
Trong ví dụ sau, chúng tôi đã sử dụng cả đối sánh mẫu và đệ quy để tính giai thừa của 5.
fact :: Int -> Int
fact 0 = 1
fact n = n * fact ( n - 1 )
main = do
putStrLn "The factorial of 5 is:"
print (fact 5)
Nó sẽ tạo ra kết quả sau:
The factorial of 5 is:
120
Cho đến bây giờ, những gì chúng ta đã thấy là các hàm Haskell nhận một kiểu làm đầu vào và tạo ra một kiểu 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. Các hàm thứ tự 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ù nó là một khái niệm ảo, nhưng trong các chương trình thế giới thực, mọi chức năng mà chúng ta 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 hàm thư viện của Haskell, thì bạn sẽ thấy rằng hầu hết các hàm thư viện đã được viết theo cách thức cao hơn. Hãy để chúng tôi lấy một ví dụ trong đó chúng tôi sẽ nhập một bản đồ hàm bậc cao có sẵn và sử dụng bản đồ đó để triển khai một hàm bậc cao khác theo sự lựa chọn của chúng ta.
import Data.Char
import Prelude hiding (map)
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map func (x : abc) = func x : map func abc
main = print $ map toUpper "dongthoigian.net"
Trong ví dụ trên, chúng ta đã sử dụng hàm toUpper của Type Class Char để chuyển đầu vào của chúng ta thành chữ hoa. Ở đây, phương thức “map” đang nhận một hàm làm đối số và trả về kết quả đầu ra được yêu cầu. Đây là đầu ra của nó
sh-4.3$ ghc -O2 --make *.hs -o main -threaded -rtsopts
sh-4.3$ main
"dongthoigian.net"
Đôi khi chúng ta phải viết một hàm chỉ được sử dụng một lần, trong toàn bộ 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 .
Một hàm không có định nghĩa được gọi là hàm lambda. Một hàm lambda được biểu thị bằng ký tự “\”. Chúng ta hãy lấy ví dụ sau, nơi chúng ta sẽ tăng giá trị đầu vào lên 1 mà không cần tạo bất kỳ hàm nào.
main = do
putStrLn "The successor of 4 is:"
print ((\x -> x + 1) 4)
Ở đây, chúng tôi đã tạo một hàm ẩn danh không có tên. Nó lấy số nguyên 4 làm đối số và in ra giá trị đầu ra. Về cơ bản chúng ta đang vận hành một hàm mà không cần 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 kết quả sau:
sh-4.3$ main
The successor of 4 is:
5
Haskell – Thêm về các chức năng (xem thêm)
The post Haskell – Chức năng appeared first on Dongthoigian.net.
]]>The post Haskell – Types and Type Class appeared first on Dongthoigian.net.
]]>Trong Haskell, mọi câu lệnh được coi là một biểu thức toán học và phạm trù của biểu thức này được gọi là Kiểu . 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ề Type , chúng ta sẽ sử dụng lệnh “: t”. Nói một cách chung chung, Type có thể được coi là một giá trị, trong khi Type Class có thể được coi là một tập hợp các loại Type tương tự nhau. Trong chương này, chúng ta sẽ tìm hiểu về các loại Inbuilt khác nhau.
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 loại Int . Trong ví dụ sau, hàm fType () sẽ hoạt động theo kiểu của nó được xác định.
fType :: Int -> Int -> Int
fType x y = x*x + y*y
main = print (fType 2 4)
Ở đây, chúng ta đã đặt kiểu của 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 kết quả sau:
sh-4.3$ ghc -O2 --make *.hs -o main -threaded -rtsopts
sh-4.3$ main
20
Số nguyên có thể được coi là một tập siêu của Int . Giá trị này không bị giới hạn bởi bất kỳ số nào, do đó một Số nguyên có thể có độ dài bất kỳ mà không có bất kỳ giới hạn nào. Để thấy sự khác biệt cơ bản giữa kiểu Int và Integer , chúng ta hãy sửa đổi đoạn mã trên như sau:
fType :: Int -> Int -> Int
fType x y = x*x + y*y
main = print (fType 212124454 44545454454554545445454544545)
Nếu bạn biên dịch đoạn mã trên, thông báo lỗi sau sẽ được đưa ra:
main.hs:3:31: Warning:
Literal 44545454454554545445454544545 is out of the Int range -
9223372036854775808..9223372036854775807
Linking main ...
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 số giá trị kiểu Int lớn thực sự. Để tránh lỗi này, Chúng ta hãy sửa đổi kiểu “Int” bằng “Số nguyên” và quan sát sự khác biệt.
fType :: Integer -> Integer -> Integer
fType x y = x*x + y*y
main = print (fType 212124454 4454545445455454545445445454544545)
Bây giờ, nó sẽ tạo ra kết quả sau:
sh-4.3$ main
1984297512562793395882644631364297686099210302577374055141
Hãy xem đoạn mã sau. Nó cho thấy cách hoạt động của kiểu Float trong Haskell
fType :: Float -> Float -> Float
fType x y = x*x + y*y
main = print (fType 2.5 3.8)
Hàm nhận 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 kết quả sau:
sh-4.3$ main
20.689999
Double
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:
Double
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:
fType :: Double -> Double -> Double
fType x y = x*x + y*y
main = print (fType 2.56 3.81)
Khi bạn thực thi đoạn mã trên, nó sẽ tạo ra kết quả sau:
sh-4.3$ main
21.0697
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:
main = do
let x = True
if x == False
then putStrLn "X matches with Bool Type"
else putStrLn "X is not a Bool Type"
Ở đâ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 kết quả sau:
sh-4.3$ main
X is not a Bool Type
Char đại diện cho các ký tự. Bất cứ thứ gì trong một trích dẫn duy nhất đều được coi là một Nhân vậ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 dưới dạng đầu ra.
fType :: Char-> Char
fType x = 'K'
main = do
let x = 'v'
print (fType x)
Đoạn mã trên sẽ gọi hàm fType () với giá trị char là ‘v’ nhưng nó trả về một giá trị char khác, đó là ‘K’. Đây là đầu ra của nó
sh-4.3$ main
'K'
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 để 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 đánh máy mạnh mẽ như thế nào.
Lớp kiểu EQ là một giao diện cung cấp chức năng kiểm tra tính bình đẳng của một biểu thức. Bất kỳ lớp Kiểu nào muốn kiểm tra tính bình đẳng của một biểu thức phải là một phần của Lớp Kiểu 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 kiểm tra bất kỳ sự bình đẳng nào bằng cách sử dụng bất kỳ kiểu nào được đề cập ở trên, chúng tôi thực sự đang thực hiện một cuộc gọi đến lớp kiểu EQ . Trong ví dụ sau, chúng tôi đang sử dụng Loại EQ nội bộ bằng thao tác “==” hoặc “/ =”
main = do
if 8 /= 8
then putStrLn "The values are Equal"
else putStrLn "The values are not Equal"
Nó sẽ mang lại kết quả sau:
sh-4.3$ main
The values are not Equal
Ord là một lớp giao diện khác cung cấp cho chúng ta chức năng đặt hàng. Tất cả các loại mà chúng tôi đã sử dụng cho đến nay là một phần của giao diện Ord này . Giống như giao diện EQ, giao diện Ord có thể được gọi bằng cách sử dụng “>”, “<“, “<=”, “> =”, “so sánh”.
ví dụ dưới đây, nơi chúng tôi đã sử dụng chức năng “so sánh”
main = print (4 <= 2)
Tại đây, trình biên dịch Haskell sẽ kiểm tra xem 4 có nhỏ hơn hoặc bằng 2. Vì không, mã sẽ tạo ra kết quả sau:
sh-4.3$ main
False
Show có chức năng in đối số của nó dưới dạng Chuỗi. Dù có thể là đối số của nó, nó luôn in ra kết quả dưới dạng một 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.
main = print (show [1..10])
Nó sẽ tạo ra kết quả sau trên bảng điều khiển. Ở đây, dấu ngoặc kép chỉ ra rằng đó là một giá trị kiểu Chuỗi.
sh-4.3$ main
"[1,2,3,4,5,6,7,8,9,10]"
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 đọc giao diện để đọc một chuỗi giá trị và chuyển đổi tương tự thành một giá trị Int.
main = print (readInt "12")
readInt :: String -> Int
readInt = read
Ở đây, chúng ta đang chuyển một biến Chuỗi (“12”) đến phương thức readInt , lần lượt nó sẽ trả về 12 (một giá trị Int) sau khi chuyển đổi. Đây là đầu ra của nó –
sh-4.3$ main
12
Enum là một loại lớp Type khác cho phép thực hiện chức năng tuần tự hoặc có thứ tự trong Haskell. Lớp Type 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 đây cho biết cách tìm giá trị kế tiếp của 12.
Enum
Enum là một loại lớp Type khác cho phép thực hiện chức năng tuần tự hoặc có thứ tự trong Haskell. Lớp Type 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 đây cho biết cách tìm giá trị kế tiếp của 12.
main = print (succ 12)
main = print (succ 12)
Nó sẽ tạo ra kết quả sau:
sh-4.3$ main
13
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 đây cho thấy cách Haskell xác định giới hạn tối đa và tối thiểu của loại Int.
main = do
print (maxBound :: Int)
print (minBound :: Int)
Nó sẽ tạo ra kết quả sau:
sh-4.3$ main
9223372036854775807
-9223372036854775808
Bây giờ, hãy cố gắng tìm giới hạn tối đa và tối thiểu của các loại Char, Float và Bool.
Lớp kiểu này được sử dụng cho các phép toán 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:
main = do
print(2 :: Int)
print(2 :: Float)
Nó sẽ tạo ra kết quả sau:
sh-4.3$ main
2
2.0
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 type chỉ được sử dụng cho các số tích phân. Int và Integer là các kiểu thuộc lớp Kiểu này.
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 loại này.
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 kiểu do người dùng xác định. Trong ví dụ sau, chúng tôi sẽ tạo một kiểu do người dùng xác định và sử dụng nó.
data Area = Circle Float Float Float
surface :: Area -> Float
surface (Circle _ _ r) = pi * r ^ 2
main = print (surface $ Circle 10 20 10 )
Ở đây, chúng tôi đã tạo một loại mới có tên là Khu vực . Tiếp theo, chúng ta đang sử dụng kiểu này để tính diện tích của một hình tròn. Trong ví dụ trên, “surface” là một hàm lấy Area 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 một chữ cái viết hoa. Nó sẽ tạo ra kết quả sau:
sh-4.3$ main
314.15927
Haskell – Chức năng (xem thêm)
The post Haskell – Types and Type Class appeared first on Dongthoigian.net.
]]>The post Haskell – Các toán tử cơ bản appeared first on Dongthoigian.net.
]]>Trong chương này, sẽ sử dụng các toán tử khác nhau trong Haskell bằng nền tảng trực tuyến 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.
Như tên cho thấy, toán tử cộng (+) được sử dụng cho chức năng cộng. Mã mẫu sau đây cho thấy cách bạn có thể thêm hai số nguyên trong Haskell:
main = do
let var1 = 2
let var2 = 3
putStrLn "The addition of the two numbers is:"
print(var1 + var2)
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 cách sử dụng Ngoài nhà điều hành. 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 ra kết quả sau trên màn hình:
The addition of the two numbers is: 5
Như tên cho thấy, toán tử này được sử dụng cho hoạt động trừ. Mã mẫu sau đây cho thấy cách bạn có thể trừ hai số nguyên trong Haskell:
main = do
let var1 = 10
let var2 = 6
putStrLn "The Subtraction of the two numbers is:"
print(var1 - var2)
Trong ví dụ này, chúng tôi đã tạo hai biến var1 và var2 . Sau đó, chúng ta sử dụng toán tử trừ (-) để trừ hai giá trị.
Mã này sẽ tạo ra kết quả sau trên màn hình:
The Subtraction of the two numbers is: 4
Toán tử này được sử dụng cho các phép toán nhân. Đoạn mã sau đây cho thấy cách nhân hai số trong Haskell bằng Toán tử nhân
main = do
let var1 = 2
let var2 = 3
putStrLn "The Multiplication of the Two Numbers is:"
print(var1 * var2)
Mã này sẽ tạo ra kết quả sau, khi bạn chạy nó trong nền tảng trực tuyến của chúng tôi –
The Multiplication of the Two Numbers is: 6
Hãy xem đoạn mã sau. Nó chỉ ra cách bạn có thể chia hai số trong Haskell
main = do
let var1 = 12
let var2 = 3
putStrLn "The Division of the Two Numbers is:"
print(var1/var2)
Nó sẽ tạo ra kết quả sau:
The Division of the Two Numbers is: 4.0
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 trong khi khai báo danh sách với một chuỗi 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 nhập “[a..z]” . Đoạn mã sau đây cho thấy cách bạn có thể sử dụng toán tử Trình tự để in tất cả các giá trị từ 1 đến 10
main :: IO()
main = do
print [1..10]
Nó sẽ tạo ra kết quả sau: [1,2,3,4,5,6,7,8,9,10]
Ra quyết định là một tính năng cho phép lập trình viên áp dụng một điều kiện trong dòng mã. Người lập trình có thể thực hiện một tập hợp các lệnh tùy thuộc vào một đ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:
Haskell cung cấp các loại tuyên bố ra quyết định sau:
Sr.No. | Tuyên bố & Mô tả |
1 | câu lệnh if – else Một khi tuyên bố với một người khác tuyên bố. Lệnh trong khối else sẽ chỉ thực thi khi điều kiện Boolean đã cho không thỏa mãn. |
2 | Câu lệnh if-else lồng nhau Nhiều khối if theo sau bởi khối else |
Đây là cú pháp chung của việc sử dụng câu lệnh điều kiện if-else trong Haskell.
if<Condition> then <True-Value>else <False-Value>
Trong biểu thức trên,
Vì mã Haskell được hiểu là các biểu thức toán học, câu lệnh trên sẽ tạo ra một lỗi mà không có khối khác . Đoạn mã sau đây cho thấy cách bạn có thể sử dụng câu lệnh if-else trong Haskell:
main = do
let var = 23
if var `rem` 2 == 0
then putStrLn "Number is Even"
else putStrLn "Number is Odd"
Trong ví dụ trên, điều kiện đã cho không thành công. Do đó, khối khác sẽ được thực thi. Nó sẽ tạo ra kết quả sau:
Number is Odd
Trong ví dụ trên, chúng ta đã thấy việc sử dụng câu lệnh if-else trong Haskell. Ở đây, chúng ta sẽ học cách sử dụng nhiều câu lệnh if-else trong một chương trình Haskell.
Trong Haskell, nhiều dòng if sẽ được sử dụng bằng cách tách từng câu lệnh if với câu lệnh else tương ứng của nó . Đoạn mã sau đây cho thấy cách bạn có thể sử dụng câu lệnh if-else lồng nhau trong Haskell:
main = do
let var = 26
if var == 0
then putStrLn "Number is zero"
else if var `rem` 2 == 0
then putStrLn "Number is Even"
else putStrLn "Number is Odd"
Trong ví dụ trên, chúng tôi đã giới thiệu nhiều điều kiện trong một hàm. Tùy thuộc vào các đầu vào chức năng, nó sẽ cung cấp cho chúng ta các đầu ra khác nhau. Bạn có thể thay đổi giá trị của biến “var” để kiểm tra tất cả các điều kiện.
Mã của chúng tôi sẽ tạo ra kết quả sau: Number is Even
Haskell – Types and Type Class (xem thêm)
The post Haskell – Các toán tử cơ bản appeared first on Dongthoigian.net.
]]>The post Haskell – Mô hình dữ liệu cơ bản appeared first on Dongthoigian.net.
]]>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
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
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.
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ó.
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'
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 .
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.
Haskell – Các toán tử cơ bản (xem thêm)
The post Haskell – Mô hình dữ liệu cơ bản appeared first on Dongthoigian.net.
]]>The post Hướng dẫn Haskell appeared first on Dongthoigian.net.
]]>Hướng dẫn này đã được chuẩn bị cho người mới bắt đầu để họ hiểu các khái niệm cơ bản về lập trình hàm sử dụng Haskell làm ngôn ngữ lập trình. Mặc dù đây là hướng dẫn dành cho người mới bắt đầu, chúng tôi giả định rằng người đọc có khả năng tiếp xúc hợp lý với bất kỳ môi trường lập trình nào và có kiến thức về các khái niệm cơ bản như biến, lệnh, cú pháp, v.v.
Haskell là một Ngôn ngữ lập trình chức năng được thiết kế đặc biệt để xử lý các ứng dụng tính toán biểu tượng và xử lý danh sách. Lập trình hàm dựa trên các hàm toán học. Bên cạnh Haskell, một số ngôn ngữ phổ biến khác tuân theo mô hình Lập trình chức năng bao gồm: Lisp, Python, Erlang, Racket, 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 phép tính được coi là sự kết hợp của các hàm toán học riêng biệt.
Haskell là một ngôn ngữ thuần chức năng được sử dụng rộng rãi. Ở đây, chúng tôi đã liệt kê ra một vài điểm khiến ngôn ngữ này trở nên đặc biệt 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.
Các chương trình chức năng đồng thời hơn và chúng tuân theo song song trong quá trình thực thi để cung cấp hiệu suất chính xác hơn và tốt hơn. Haskell không phải là ngoại lệ; nó đã được phát triển theo cách để xử lý đa luồng một cách hiệu quả.
Đó là một ví dụ đơn giản để chứng minh sự 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 “Hello 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 kết quả sau:
Hello World
Chúng tôi sẽ cung cấp nhiều ví dụ trong suốt hướng dẫn này để giới thiệu sức mạnh và sự đơn giản của Haskell.
Trình soạn thảo trực tuyến này có rất nhiều tùy chọn để thực hành các ví dụ lập trình Haskell. Đi tới 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ả đầu ra 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.org/downloads
Có ba loại trình cài đặt khác nhau có sẵn trên thị trường –
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, bây giờ chúng ta hãy 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 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.org/platform/windows.html và tải xuống Trình cài đặt theo kiến trúc có thể tùy chỉnh của bạn.
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ư bất kỳ ứng dụng Windows nào khác. Bạn có thể cần cập nhật cấu hình CABAL của hệ thống của mình.
Để 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.org/platform/mac.html và tải xuống trình cài đặt Mac.
Cài đặt Haskell trên một 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ó là mệt mỏi nhưng nó là đá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.org/platform/linux.html và chọn bả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.
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 của mình với lệnh cài đặt Haskell trong hệ thống cục bộ của chúng tôi.
Bước 3 – Mở một thiết bị đầu cuối 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 một thông báo xác nhận.
Bước 4 – Truy cập 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.
Để thoát khỏi GHCI prolog, bạn có thể sử dụng lệnh “: thoát khỏi lối ra”
The post Hướng dẫn Haskell appeared first on Dongthoigian.net.
]]>