Haskell:一个不是Functor(或者不可穿越)的Foldable的例子?
一个Foldable
实例可能是某种容器,所以也可能是一个Functor
。 事实上, 这就是说
一个
Foldable
types也是一个容器(虽然这个类在技术上并不需要Functor
,有趣的Foldable
s都是Functor
的)。
那么有没有一个自然是Functor
或Traversable
的Foldable
的例子? (这也许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
定义的专用fold
和map
函数的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