Haskell - Functor
Functortrong 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ạ. Đó là một khái niệm cấp cao của việc 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. đều là thể hiện của Haskell Functor.
A Functor là một lớp có sẵn với định nghĩa hàm như -
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, fmap()và trả về một hàm khác. Trong ví dụ trên,fmap() là một đại 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.
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ả hai map() và fmap()trên một danh sách cho một phép toán trừ. Bạn có thể quan sát 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? 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
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.
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 xác định 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àApplicative Functor. Cơ sở ánh xạ này được thực hiện bởi lớp Loại ứng dụng được định nghĩa trongControlmô-đun. Lớp này chỉ cung cấp cho chúng ta hai phương thức để làm việc: một làpure và cái kia 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ể lập bản đồ 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 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 kết quả sau.
"Just 4"
Monoids
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 dưới dạng đầu ra của hàm. Đây là những gì mộtMonoid Là.
A Monoidlà 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 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 "đa" 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 chức năng{(*),1} và {(+),0} là những ví dụ hoàn hảo về monoids.