Tôi nghĩ có một vài yếu tố gây căng thẳng ở đây. Có ý tưởng chung là định nghĩa loại lớp phải là tối thiểu và chỉ chứa độc lập chức năng.Vì câu trả lời của bhelkir giải thích, nếu lớp của bạn hỗ trợ các hàm a
, b
và c
, nhưng c
có thể được triển khai theo số a
và b
, đó là một đối số để xác định c
bên ngoài lớp học.
Nhưng ý tưởng chung này gặp phải một số vấn đề xung đột khác.
Đầu tiên, thường có nhiều bộ hoạt động tối thiểu có thể xác định tương tự cùng một lớp. Định nghĩa cổ điển của Monad
trong Haskell là này (dọn dẹp một chút):
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Nhưng nó cũng biết rằng có những định nghĩa khác, như thế này một:
class Applicative m => Monad m where
join :: m (m a) -> m a
return
và >>=
là đủ để triển khai join
, nhưng fmap
, pure
và join
cũng đủ để triển khai >>=
.
Điều tương tự với Applicative
. Đây là kinh điển định nghĩa Haskell:
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
Nhưng bất cứ điều nào sau đây là tương đương:
class Functor f => Applicative f where
unit :: f()
(<*>) :: f (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
fpair :: f a -> f b -> f (a, b)
class Functor f => Applicative f where
unit :: f()
fpair :: f a -> f b -> f (a, b)
class Functor f => Applicative f where
unit :: f()
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
Với bất kỳ các định nghĩa lớp, bạn có thể viết bất kỳ phương pháp trong bất kỳ những người khác như một hàm bắt nguồn bên ngoài lớp. Tại sao người đầu tiên được chọn? Tôi không thể trả lời tác giả, nhưng tôi nghĩ nó đưa chúng ta đến điểm thứ ba: cân nhắc hiệu suất. Các hoạt động fpair
trong nhiều người kết hợp các giá trị f a
và f b
bằng cách tạo ra các bộ, nhưng đối với hầu hết cách dùng lớp Applicative
chúng tôi không thực sự muốn những bộ dữ liệu, chúng tôi chỉ muốn kết hợp các giá trị rút ra từ f a
và f b
; định nghĩa kinh điển cho phép chúng ta chọn chức năng nào để thực hiện kết hợp này.
Một xem xét hiệu suất là ngay cả khi một số phương pháp trong một lớp có thể định nghĩa về người khác, những định nghĩa chung chung có thể không tối ưu cho tất cả các trường của lớp. Nếu chúng tôi lấy Foldable
làm ví dụ, foldMap
và foldr
là không thể xác định được, nhưng một số loại hỗ trợ một cách hiệu quả hơn loại kia. Vì vậy, thông thường chúng ta có các định nghĩa lớp không tối thiểu để cho phép các cá thể cung cấp việc triển khai tối ưu các phương thức.
Sự phân biệt nhỏ: '<,> 'không phải là tên nhà điều hành hợp pháp. –
@ ØrjanJohansen: D'oh! Tôi đã đổi nó thành 'fpair' (tên được tạo thành, một chút tương tự với' fmap'). –
Ưu điểm của việc giữ các loại lớp tối thiểu khi bổ sung của bạn ở mức tối thiểu có triển khai mặc định dựa trên giao diện tối thiểu là gì? – timdiels