【问题标题】:Terminology of the Traversable conceptTraversable 概念的术语
【发布时间】:2018-06-19 15:51:56
【问题描述】:

为什么我们将结构的翻转称为“序列”,为什么我们要谈论“遍历”和“遍历”?

我正在将这些概念的实现添加到 haskell 中以供讨论...

class (Functor t, Foldable t) => Traversable t where
    {-# MINIMAL traverse | sequenceA #-}

    -- | Map each element of a structure to an action, evaluate these actions
    -- from left to right, and collect the results. For a version that ignores
    -- the results see 'Data.Foldable.traverse_'.
    traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
    traverse f = sequenceA . fmap f

    -- | Evaluate each action in the structure from left to right, and
    -- and collect the results. For a version that ignores the results
    -- see 'Data.Foldable.sequenceA_'.
    sequenceA :: Applicative f => t (f a) -> f (t a)
    sequenceA = traverse id

【问题讨论】:

  • sequence(动词):将可遍历的“容器”“内部”的应用“动作”序列(名词)转化为产生结果序列的应用“动作”。对于列表,可以定义为sequenceA = foldr (liftA2 (:)) (pure [])traverse 可以称为 mapA,因为它与 mapM 平行。我猜映射是一种遍历。
  • 另外,对于列表,sequence [] = return [] ; sequence (x:xs) = do { x <- x; xs <- sequence xs; return (x:xs) } 其中所有“计算”xs 都是预先知道的,因此 Monad 的全部功能能够根据先前运行的计算结果创建新计算(如y <- foo x) 实际上不需要。因此,Applicative Functor 是一个比 Monadic Functor 更不强大、更通用的 Functor。

标签: haskell category-theory traversable


【解决方案1】:

让我们从考虑fmap开始:

fmap :: Functor t => (a -> b) -> t a -> t b

我们可以将它的作用描述为在t a 中查找所有a 值并将函数应用于它们。请注意,除了无限的结构恶作剧之外,fmap 的实现到达a 值以修改它们的顺序对于最终结果而言并不重要。

现在让我们看看traverse

traverse :: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)

fmap 一样,traverse 也涉及将函数应用于结构中的值(难怪traverse 的前身被称为mapM)。然而,traverse 也会为每个a 值(a -> f b 中的f)产生应用效果,并且它涉及以某种顺序组合这些效果以获得整体f (t b) 结果。通常(即只要f 不是可交换应用程序,例如Maybe),效果的顺序会影响结果。既然如此,任何Traversable 实例都对应于访问结构中的值的特定顺序。 “穿越”这个名称(即,正如 Will Ness 所指出的,“穿越或穿过”)旨在传达这种方向感。

在相关说明中,traverse 可以分解为一个普通映射,该映射会产生效果,然后对这些效果进行排序...

sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)

traverse f = sequenceA . fmap f
sequenceA = traverse id

...因此“序列”名称。

还值得强调的是,traverse 确实捕获了通过结构和在每一站做事的各种方式(参见forflip traverse 的名称)。特别是,我们通过选择 Identity 作为 Applicative 函子(即实际上不产生任何效果)来恢复 fmap,并通过选择 Monoid m => Const m 来恢复 foldMap(即类似列表的折叠)。我们不能traverse 做的事情包括删除、复制或重新排列元素——它不允许像一般折叠/变态那样以任意方式拆除数据结构。使用traverse,我们可以在Traversable 结构中移动,但我们无法重塑它。

【讨论】:

  • 谢谢@duplode!
  • @NicolasHenin 欢迎您。我忘了提及:在 Haskell 中,双重“结构翻转”最流行的名称是 distribute :: (Functor f, Distributive g) => f (g a) -> g (f a)。 (话说回来,一篇关于Traversable 的关键论文使用dist 作为sequenceA 的名称,我想这只是说明了命名事物的难度。)
【解决方案2】:

这是“to 序列”,而不是“a”。 IE。 "Arrange in a particular order",这里从左到右。而且是sequence :: Monad m => [m a] -> m [a]的泛化(注意旧的base版本),可能会让名字更明显。

【讨论】:

  • 好酷,有道理..那为什么要遍历/遍历?
  • 这对我来说很难说。尝试查看hackage.haskell.org/package/base-4.11.1.0/docs/…中链接的论文?
  • “traverse”是简单的英文:“travel across or through”。即以某种线性方式枚举容器t a 内的所有元素a。就像枚举二叉树中的节点一样。或枚举a tree's fringe
  • 我有点不喜欢的是sequenceA 似乎更基本(只需查看描述),但该类仍然以traverse 命名:)
猜你喜欢
  • 2020-08-28
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 2021-06-03
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
  • 2010-10-10
相关资源
最近更新 更多