Reading Beautiful folding tôi nhận ra rằng bất kỳ Foldable
thể được thực hiện một Functor
bằng cách gói nó vào
data Store f a b = Store (f a) (a -> b)
với một contructor thông minh đơn giản:
store :: f a -> Store f a a
store x = Store x id
(Đây chỉ là một biến thể của Store loại dữ liệu comonad.)
Bây giờ chúng tôi có thể xác định
instance Functor (Store f a) where
fmap f (Store x g) = Store x (f . g)
instance (F.Foldable f) => F.Foldable (Store f a) where
foldr f z (Store x g) = F.foldr (f . g) z x
Bằng cách này, chúng tôi có thể làm cho cả hai Data.Set.Set
và Sjoerd Visscher là Weird
một hàm. (Tuy nhiên, vì cấu trúc không ghi nhớ các giá trị của nó, việc lặp lại nhiều lần so với nó có thể rất không hiệu quả, nếu hàm mà chúng ta sử dụng trong fmap
là phức tạp.)
Cập nhật: này cũng cung cấp một ví dụ về một cấu trúc đó là một functor, có thể gập lại nhưng không traversable. Để thực hiện Store
có thể di chuyển, chúng tôi cần phải thực hiện (->) r
có thể di chuyển. Vì vậy, chúng tôi cần phải thực hiện
sequenceA :: Applicative f => (r -> (f a)) -> f (r -> a)
Chúng ta hãy Either b
cho f
. Sau đó, chúng tôi cần phải thực hiện
sequenceA' :: (r -> Either b a) -> Either b (r -> a)
Rõ ràng, không có chức năng đó (bạn có thể xác minh với Djinn). Vì vậy, chúng tôi không thể nhận ra sequenceA
.
Nguồn
2012-10-15 13:21:22
Ồ, thật tuyệt! Thậm chí không nghĩ về điều đó. Tự hỏi liệu có bất kỳ trường hợp 'Có thể gập lại 'nào trong các thư viện chuẩn-ish mà không phải là một' Functor' do contravariance? –
Tôi nghĩ bạn có thể làm điều đó với các phần mở rộng nhất định và nhập các từ đồng nghĩa. – PyRulez