[英]How does Traversable use the fact that it subclasses both Foldable and Functor?
[英]An example of a Foldable which is not a Functor (or not Traversable)?
這是一個完全參數化的例子:
data Weird a = Weird a (a -> a)
instance Foldable Weird where
foldMap f (Weird a b) = f $ b a
Weird
的不是一個Functor
因為a
處於負面位置。
這是一個簡單的例子: Data.Set.Set
。 你自己看。
如果您檢查為Set
定義的專用fold
和map
函數的類型,原因應該是顯而易見的:
foldr :: (a -> b -> b) -> b -> Set a -> b
map :: (Ord a, Ord b) => (a -> b) -> Set a -> Set b
由於數據結構在內部依賴於二叉搜索樹,因此元素需要Ord
約束。 Functor
實例必須允許任何元素類型,因此這是不可行的,唉。
另一方面,折疊總是破壞樹以產生匯總值,因此不需要對折疊的中間結果進行排序。 即使折疊實際上構建了一個新的Set
,滿足Ord
約束的責任在於傳遞給折疊的累積函數,而不是折疊本身。
同樣可能適用於任何不完全參數化的容器類型。 鑒於Data.Set
的實用性,我認為你引用的關於“有趣” Foldable
評論似乎有點可疑!
閱讀美麗的折疊我意識到任何Foldable
都可以通過包裝成為Functor
data Store f a b = Store (f a) (a -> b)
使用簡單的智能構造器:
store :: f a -> Store f a a
store x = Store x id
(這只是Store comonad數據類型的變體。)
現在我們可以定義
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
通過這種方式,我們可以使Data.Set.Set
和Sjoerd Visscher的Weird
成為一個Data.Set.Set
函數。 (但是,由於結構不會記住它的值,如果我們在fmap
使用的fmap
很復雜,那么重復折疊它可能是非常低效的。)
更新:這也提供了一個結構的示例,該結構是一個可折疊但可折疊但不可遍歷的仿函數。 要使Store
遍歷,我們需要使(->) r
遍歷。 所以我們需要實施
sequenceA :: Applicative f => (r -> (f a)) -> f (r -> a)
讓我們把Either b
取為f
。 然后我們需要實施
sequenceA' :: (r -> Either b a) -> Either b (r -> a)
顯然,沒有這樣的功能(你可以用Djinn驗證)。 所以我們既不能實現sequenceA
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.