【问题标题】:What would be the "distinct method" that Traversable has in addition to Foldable?Traversable 除了 Foldable 之外还有什么“独特的方法”?
【发布时间】:2014-01-31 16:26:16
【问题描述】:

FoldableTraversable 的超类,类似于FunctorApplicativeMonad 的超类。

类似于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 =&gt; (,) 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 = ...

我不是在问,因为我需要这个特定的东西;这是一个概念问题,以便更好地理解FoldableTraversable 之间的区别。同样很像Monad vs Functor:而&gt;&gt;=join 更方便日常Haskell 编程(因为您通常需要fmapjoin 的这种组合 ),后者更容易理解 monad 的含义。

【问题讨论】:

  • 不同的方法是traverse。你不能用Foldable来实现它。
  • 当然不是,但是你可以按照traverse来实现Foldable
  • ...这就是为什么FoldableTraversable 的超类。就子类而言,超类应该是可实现的。
  • 我认为@leftaroundabout 要求相当于:您能否定义一个类TraversableMinusFoldable,以便`class (Foldable t, TraversableMinusFoldable t) => Traversable t where` 没有新功能,但现有功能兼容。例如,您能否在不引用 Foldable 中的任何内容的情况下定义 traverse。但即使这是问题所在,我也不相信这不是他研究情况的正确方法。旧的 Monad 是一团糟,最好忘记 :-)
  • @misterbee:差不多就是这样,但不完全是。我感兴趣的只是你可以给出Traversable的方法的“最弱签名”,所以实际使用实际上需要超类Foldable。目前,您基本上可以像历史上的Monad 那样省略超类,正如您所说的那样不好。

标签: haskell containers fold traversable


【解决方案1】:

Foldable 对应于Functor,就像Traversable 对应于Monad,即FoldableFunctorMonadTraversable 的超类(对所有应用程序/monad 提案噪声取模)。

确实,这已经在代码中了

instance Foldable f => Traversable f where
  ...

所以,还不清楚还需要什么。 Foldable 的特点是toList :: Foldable f =&gt; f a -&gt; [a]Traversable 最终不仅取决于能够像toList 那样将内容抽象为列表,还取决于能够提取形状

shape :: Functor f => f a -> f ()
shape = fmap (const ())

然后重新组合它们

combine :: Traversable f => f () -> [a] -> Maybe (f a)
combine f_ = evalStateT (traverse pop f_) where
  pop :: StateT [a] Maybe a
  pop = do x <- get
           case x of
             [] = empty
             (a:as) = set as >> return a

这取决于traverse

有关此属性的更多信息,请参阅this blog post by Russell O'Connor

【讨论】:

  • 那么,如果combineTraversable的唯一方法,就可以定义traverse/sequenceA吗?
  • 我可能会说 Foldable 之于 Functor 就像 Traversable 之于 Applicative
  • @leftaroundabout 试试看,如果遇到困难就发帖 :-)
  • 好的,所以我们可以实现sequenceA q = let { structure = fmap (const()) q; values = toList q } in fmap (fromJust . combine structure) $ Prelude.sequence values。我想如果我们需要combine (fmap (const()) q) (toList q) 总是“有效”的公理,结果是Just,这就足够了。这似乎回答了我的问题,但正如你所说的 combine 看起来并不完全优雅。
  • 如果我们有依赖类型,我们可以写combine :: Traversable f =&gt; Πx:f (). Vec a (length x) -&gt; f a。我们可以在不使用依赖类型的情况下创建 Traversable 类的事实有点令人惊讶。这可能与它使用应用函子的辅助类并假设它们遵循它们的规律这一事实有关。
【解决方案2】:

超级手波,因为它已经晚了,但是TraversableFoldable 具有的额外功能是一种重建原始结构的方法。例如,使用列表:

module MyTraverse where

import Data.Foldable
import Data.Traversable
import Control.Applicative
import Data.Monoid

data ListRec f x = ListRec
  { el :: f (Endo [x])
  }

instance Applicative f => Monoid (ListRec f x) where
    mempty = ListRec (pure mempty)
    mappend (ListRec l) (ListRec r) =
        ListRec (mappend <$> l <*> r)

toM :: Functor f => f b -> ListRec f b
toM this = ListRec $ (Endo . (:)) <$> this

fromM :: Functor f => ListRec f b -> f [b]
fromM (ListRec l) = flip appEndo [] <$> l

myTraverse :: Applicative f => (a-> f b)  -> [a] -> f [b]
myTraverse f xs = fromM $ foldMap (toM . f) xs

我认为这个myTraverse 的行为与traverse 相同,只使用ApplicativeFoldableMonoid 类。如果你想摆脱Monoid,你可以重写它以使用foldr 而不是foldMap

列表很简单,因为它们是扁平结构。但是,我强烈怀疑您可以使用 Zipper 为任何结构获得正确的重建函数(因为 zippers 通常是可导出的,它们应该始终存在)。

但即使使用拉链,您也无法向 monoid/函数指示该结构。从概念上讲,Traversable 似乎添加了类似

class Traversed t where
  type Path t :: *
  annotate :: t a -> [(Path t, a)]
  fromKeyed :: [(Path t, a)] -> t a

这似乎与Foldable 重合,但我认为在尝试将路径与其组成值相关联时这是不可避免的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多