【发布时间】:2014-01-31 16:26:16
【问题描述】:
Foldable 是Traversable 的超类,类似于Functor 是Applicative 和Monad 的超类。
类似于Monad的情况,基本上可以实现fmap为
liftM :: Monad m => (a->b) -> m a -> m b
liftM f q = return . f =<< q
我们也可以模仿 foldMap 为
foldLiftT :: (Traversable t, Monoid m) => (a -> m) -> t a -> m
foldLiftT f = fst . traverse (f >>> \x -> (x,x))
-- or: . sequenceA . fmap (f >>> \x -> (x, x))
使用Monoid m => (,) m monad。所以超类和方法的组合在这两种情况下都有一定的冗余。
在 monad 的情况下,可以说类型类的“更好”定义是(我将跳过 applicative / monoidal)
class (Functor m) => Monad m where
return :: a -> m a
join :: m (m a) -> m a
至少那是范畴论中使用的。这个定义在不使用Functor 超类的情况下,不允许允许liftM,所以它没有这种冗余。
Traversable 类是否可以进行类似的转换?
澄清一下:我所追求的是重新定义,我们称之为,
class (Functor t, Foldable t) => Traversable t where
skim :: ???
这样我们就可以将实际的 Traverse 方法设为顶级函数
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
但它不可能通用
instance (Traversable t) => Foldable t where
foldMap = ... skim ...
data T
instance Traversable T where
skim = ...
我不是在问,因为我需要这个特定的东西;这是一个概念问题,以便更好地理解Foldable 和Traversable 之间的区别。同样很像Monad vs Functor:而>>= 比join 更方便日常Haskell 编程(因为您通常需要fmap 和join 的这种组合 ),后者更容易理解 monad 的含义。
【问题讨论】:
-
不同的方法是
traverse。你不能用Foldable来实现它。 -
当然不是,但是你可以按照
traverse来实现Foldable。 -
...这就是为什么
Foldable是Traversable的超类。就子类而言,超类应该是可实现的。 -
我认为@leftaroundabout 要求相当于:您能否定义一个类
TraversableMinusFoldable,以便`class (Foldable t, TraversableMinusFoldable t) => Traversable t where` 没有新功能,但现有功能兼容。例如,您能否在不引用Foldable中的任何内容的情况下定义traverse。但即使这是问题所在,我也不相信这不是他研究情况的正确方法。旧的 Monad 是一团糟,最好忘记 :-) -
@misterbee:差不多就是这样,但不完全是。我感兴趣的只是你可以给出
Traversable的方法的“最弱签名”,所以实际使用实际上需要超类Foldable。目前,您基本上可以像历史上的Monad那样省略超类,正如您所说的那样不好。
标签: haskell containers fold traversable