Haskell:一个不是Functor(或者不可穿越)的Foldable的例子?

一个Foldable实例可能是某种容器,所以也可能是一个Functor 。 事实上, 这就是说

一个Foldabletypes也是一个容器(虽然这个类在技术上并不需要Functor ,有趣的Foldable s都是Functor的)。

那么有没有一个自然是FunctorTraversableFoldable的例子? (这也许Haskell wiki页面错过了:-))

这是一个完全参数化的例子:

 data Weird a = Weird a (a -> a) instance Foldable Weird where foldMap f (Weird ab) = f $ ba 

Weird的不是一个Functor因为一个负面的位置。

这是一个简单的例子: Data.Set.Set 。 你自己看。

如果您检查为Set定义的专用foldmap函数的types,这个原因应该是显而易见的:

 foldr :: (a -> b -> b) -> b -> Set a -> b map :: (Ord a, Ord b) => (a -> b) -> Set a -> Set b 

由于数据结构在内部依赖二叉search树,所以元素需要Ord约束。 Functor实例必须允许任何元素types,所以这是不可行的,唉。

另一方面,折叠总是破坏树来生成汇总值,所以不需要对折叠的中间结果进行sorting。 即使折叠实际上是build立一个新的Set ,满足Ord约束的责任在于传递给折叠的累积函数,而不是折叠本身。

同样可能适用于任何不完全参数化的容器types。 考虑到Data.Set ,这使得您所引用的关于“有趣”的Foldable S的评论似乎有点可疑,我想!

阅读美丽的折叠,我意识到,任何Foldable可以通过包装成一个Functor

 data Store fab = Store (fa) (a -> b) 

用一个简单的智能构造器:

 store :: fa -> Store faa store x = Store x id 

(这只是Store comonad数据types的一个变体。)

现在我们可以定义

 instance Functor (Store fa) where fmap f (Store xg) = Store x (f . g) instance (F.Foldable f) => F.Foldable (Store fa) where foldr fz (Store xg) = F.foldr (f . g) zx 

这样,我们可以使Data.Set.Set和Sjoerd Visscher的Weird的函数。 (但是,如果我们在fmap使用的fmap是复杂的,由于结构没有记忆它的值,反复地折叠它可能是非常低效的。)


更新:这也提供了一个函子的结构的例子,可折叠但不可遍历。 为了让Store遍历,我们需要使(->) r遍历。 所以我们需要实施

 sequenceA :: Applicative f => (r -> (fa)) -> f (r -> a) 

让我们以Either b f 。 那么我们需要实施

 sequenceA' :: (r -> Either ba) -> Either b (r -> a) 

显然,没有这样的function(你可以用Djinn来validation)。 所以我们既不能实现sequenceA