【问题标题】:What does Traversable is to Applicative contexts mean?Traversable 对 Applicative 上下文意味着什么?
【发布时间】:2019-04-05 10:19:17
【问题描述】:

我试图在https://namc.in/2018-02-05-foldables-traversals 的帮助下理解 Traversable。

作者在某处提到了下面这句话:

Traversable 之于 Applicative 上下文就像 Foldable 之于 Monoid 价值观。

他试图澄清什么?

我没有得到Foldable to Monoid之间的连接。

请举个例子。

【问题讨论】:

  • 我现在不能写出正确的答案(如果没有其他人先覆盖它,我会稍后再写)。同时,我想知道您是否会在the beginning of the Wikibook chapter(本文所依据的)中找到更清晰的解释。

标签: haskell applicative monoids traversable foldable


【解决方案1】:

一开始有foldr

foldr :: (a -> b -> b) -> b -> [a] -> b

还有mapM:

mapM :: Monad m => (a -> m b) -> [a] -> m [b]

foldr 被泛化到 [a] 以外的数据类型,方法是让每种类型定义自己的 foldr 定义来描述如何将其缩减为单个值。

-- old foldr ::        (a -> b -> b) -> b -> [] a -> b
foldr :: Foldable t => (a -> b -> b) -> b -> t  a -> b

如果你有一个幺半群,你不必指定一个二元函数,因为Monoid 实例已经提供了它自己的起始值并且知道如何组合两个值,这从它的默认定义中可以明显看出foldr:

-- If m is a monoid, it provides its own function of type b -> b.
foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
foldMap f = foldr (mappend . f) mempty

Traverse 进行从列表到可遍历类型的相同类型的泛化,但对于mapM

-- old mapM ::              Monad m        => (a -> m b) -> [] a -> m ([] b)
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t  a -> f (t  b)

(当mapM 首次定义时,没有Applicative 类;如果有,则可以定义mapA :: Applicative f => (a -> f b) -> [a] -> f [b]Monad 约束比必要的要强。)

Applicative 本质上是幺半群,因此在 Traverse 中不需要 foldr/foldMap 绘制的区别类型。

【讨论】:

  • 我认为你的第一个 foldr 签名中有一个额外的斜线。
【解决方案2】:

这篇文章(和the corresponding passage of the Wikibook)正在讨论如何将应用值的效果(或者,使用那里看到的语言,上下文)组合成幺半群。与Foldable 的联系在于,类似列表的折叠最终相当于将值组合为单面体(参见chepner's answer,还有Foldr/Foldl for free when Tree is implementing Foldable foldmap?。至于应用上下文部分,有几种方法可以查看。其中之一他们注意到,对于任何Applicative fMonoid mf m 是一个幺半群,pure mempty 作为memptyliftA2 mappend 作为mappendthis Ap type from the reducers package 见证)。举个具体的例子,让我们选择f ~ Maybem ~ ()。这给我们留下了四种可能的组合:

liftA2 mappend (Just ()) (Just ()) = Just ()
liftA2 mappend (Just ()) Nothing   = Nothing
liftA2 mappend Nothing   (Just ()) = Nothing
liftA2 mappend Nothing   Nothing   = Nothing

现在对比AllBool 半群,(&&)mappend

mappend (All True)  (All True)  = All True
mappend (All True)  (All False) = All False
mappend (All False) (All True)  = All False
mappend (All False) (All False) = All False

它们完美匹配:Just () 代表TrueNothing 代表FalseliftA2 mappend 代表(&&)

现在让我们再看一下 Wikibook 示例:

deleteIfNegative :: (Num a, Ord a) => a -> Maybe a
deleteIfNegative x = if x < 0 then Nothing else Just x

rejectWithNegatives :: (Num a, Ord a, Traversable t) => t a -> Maybe (t a)
rejectWithNegatives = traverse deleteIfNegative
GHCi> rejectWithNegatives [2,4,8]
Just [2,4,8]
GHCi> rejectWithNegatives [2,-4,8]
Nothing

通过将deleteIfNegative 应用于列表中的值生成的Maybe 值按上述方式进行单曲面组合,因此我们得到Nothing,除非所有 Maybe值为Just

这个问题也可以反方向处理。通过Applicative 实例为Const...

-- I have suppressed a few implementation details from the instance used by GHC.
instance Monoid m => Applicative (Const m) where
    pure _ = Const mempty
    Const x <*> Const y = Const (x `mappend` y)

...我们可以从任何Monoid 中得到一个Applicative,这样(&lt;*&gt;) 将单曲面值组合在一起。这使得define foldMap and friends in terms of traverse成为可能。

最后一点,Applicative 作为单曲面函子类的范畴理论描述与我在此讨论的内容完全不同。有关此问题和其他细则的进一步讨论,请参阅Monoidal Functor is Applicative but where is the Monoid typeclass in the definition of Applicative?(如果您想深入了解,阅读那里的所有答案非常值得)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-04
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 2011-12-28
    相关资源
    最近更新 更多