1

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

我正在讨论这些概念的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
4

2 回答 2

3

它是“排序”,而不是“a” “按特定顺序排列”,这里从左到右。而且是对sequence :: Monad m => [m a] -> m [a](注意旧版base)的概括,可能会让名字更明显。

于 2018-06-19T17:35:06.643 回答
3

让我们从考虑开始fmap

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

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

现在让我们来看看traverse

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

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

在相关的说明中,traverse可以分解为一个简单的映射,该映射产生效果,然后是这些效果的排序......

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

traverse f = sequenceA . fmap f
sequenceA = traverse id

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

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

于 2018-06-21T15:40:02.553 回答