折叠非名单?

时间:2016-11-28 01:10:36

标签: haskell functional-programming

在最近的作业中,我被要求为某些非列表类型定义折叠函数。我还没有完全理解这个概念。到目前为止,我已将fold理解为执行list中的后续元素。 fold上的Tree仍然具有直观意义,因为人们可以在根的子树上递归地应用某些函数。

但是,在类似的数据类型上:

Maybe a :: Nothing | Just a

执行折叠操作时没有list(在我看来)。

我确定在理解这里的基本概念方面存在一些问题,我非常感谢一些清理工作。

2 个答案:

答案 0 :(得分:6)

Foldable是一个非常令人困惑的课程,说实话,因为它没有很多法律,很可能写出很多不同的{{1}几乎任何给定类型的实例。幸运的是,根据相同类型的Traversable实例(如果有的话),可以找出Foldable实例应该以纯机械方式执行的操作。

我们有

Foldable

class (Functor t, Foldable t) => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) 有几个不同的法律,但事实证明最重要的是Traversable。我们来看看这适用于traverse Identity = Identity

Maybe

现在,在第一种情况下,您需要生成traverse :: Applicative f => (a -> f b) -> Maybe a -> f (Maybe b) traverse g Nothing = _none traverse g (Just a) = _some ,而您拥有的只是f (Maybe b)。由于您没有任何g :: a -> f b值,并且您没有任何f值,因此您唯一可以生成a

在第二种情况下,您必须生成pure Nothing并且您拥有f (Maybe b)g :: a -> f b。因此,唯一有趣的方法是将a应用于g,获取a。现在你有两个选择可以考虑:你可以抛弃这个值,然后只返回g a :: f b,或者你可以把它包装在Nothing中。

根据身份法,Just。因此,您不得返回traverse Identity (Just a) = Identity (Just a)法律定义是

Nothing

traverse _ Nothing = pure Nothing traverse g (Just a) = Just <$> g a 的{​​{1}}实例完全取决于Traversable定律和参数。

现在可以使用Maybe折叠:

Traversable

这适用于traverse

foldMapDefault :: (Traversable t, Monoid m)
               => (a -> m) -> t a -> m
foldMapDefault f xs =
  getConst (traverse (Const . f) xs)

扩展我们的定义,

Maybe

根据foldMapDefault f Nothing = getConst (traverse (Const . f) Nothing) foldMapDefault f (Just a) = getConst (traverse (Const . f) (Just a)) 的{​​{1}}和foldMapDefault f Nothing = getConst (pure Nothing) foldMapDefault f (Just a) = getConst (Just <$> (Const (f a))) 的定义,这些是

pure

展开构造函数,

<$>

这确实是为Const定义foldMapDefault f Nothing = getConst (Const mempty) foldMapDefault f (Just a) = getConst (Const (f a)) 的原因。

答案 1 :(得分:3)

As&#34;基本概念&#34;去,这是非常令人费解的,所以不要感觉太糟糕。

将折叠对列表的作用放在一边,并考虑 type 特定的折叠函数(让我们使用foldr)应该具有的帮助可能会有所帮助如果应用于Maybe。写List a代替[a]以使其更清晰,列表上的标准foldr具有类型:

foldr :: (a -> b -> b) -> b -> List a -> b

显然,Maybe上的相应折叠必须有类型:

foldrMaybe :: (a -> b -> b) -> b -> Maybe a -> b

考虑一下这可能有什么定义,因为必须为所有ab定义,而不知道有关类型的任何其他内容。作为进一步的提示,看看Data.Maybe中已经定义了一个类似类型的函数 - 也许(哈哈),它会给你一些想法。