Haskell 类型foldMap::(幺半群m)=>;(a->;m)>;f a->;我的意思是,如何实施它?
有人能解释一下类型的含义以及如何实现吗Haskell 类型foldMap::(幺半群m)=>;(a->;m)>;f a->;我的意思是,如何实施它?,haskell,foldable,Haskell,Foldable,有人能解释一下类型的含义以及如何实现吗 class Foldable f where foldMap :: (Monoid m) => (a -> m) -> f a -> m 基于, 他们将其解释为“将结构的每个元素映射到一个幺半群,并结合结果。”但我不太明白它的意思。如何将元素映射到幺半群的结构 我试过了 foldMap f=mconcat。()f 但我有一个错误: • Couldn't match type ‘f’ with ‘[]’ ‘f’ i
class Foldable f where
foldMap :: (Monoid m) => (a -> m) -> f a -> m
基于,
他们将其解释为“将结构的每个元素映射到一个幺半群,并结合结果。”但我不太明白它的意思。如何将元素映射到幺半群的结构
我试过了
foldMap f=mconcat。()f
但我有一个错误:
• Couldn't match type ‘f’ with ‘[]’
‘f’ is a rigid type variable bound by
the class declaration for ‘Foldable’
at traversable.hs:41:16
Expected type: f a -> m
Actual type: [a] -> m
• In the expression: mconcat . (<$>) f
In an equation for ‘foldMap’: foldMap f = mconcat . (<$>) f
• Relevant bindings include
foldMap :: (a -> m) -> f a -> m (bound at traversable.hs:45:3)
error:
• Could not deduce (Data.Foldable.Foldable f)
arising from a use of ‘foldr’
from the context: Foldable f
bound by the class declaration for ‘Foldable’
at traversable.hs:41:7-14
or from: Monoid m
bound by the type signature for:
foldMap :: forall m a. Monoid m => (a -> m) -> f a -> m
at traversable.hs:42:14-47
Possible fix:
add (Data.Foldable.Foldable f) to the context of
the type signature for:
foldMap :: forall m a. Monoid m => (a -> m) -> f a -> m
or the class declaration for ‘Foldable’
• In the expression: foldr (\ x -> mappend (f x)) mempty
In an equation for ‘foldMap’:
foldMap f = foldr (\ x -> mappend (f x)) mempty
他们将其解释为“将结构的每个元素映射到一个幺半群,并结合结果。”但我不太明白它的意思。如何将元素映射到幺半群的结构
我们使用签名为a->m
的函数来实现这一点。所以我们自己定义“映射”函数
A是一种代数结构。它本质上是一个三元组,⊕, s0)其中S是一组值,⊕ :: S×S&右箭头;S是一个关联的二元运算符,s0是一个恒等元素,因此s0⊕ s=s
⊕ s0=s
作为的成员的类型是可以“折叠”的数据结构。这意味着,例如,如果您有一个包含Int
s的树,那么就有一个树Int
,这样,对于函数f::Int->Int->Int
,以及一个中性元素z
,您就可以派生一个Int
通过使用foldMap
我们将对这些元素调用函数f::a->m
,并使用monoid函数⊕ 要“折叠”这些值。因此,对于实现Functor
的数据结构,它或多或少相当于foldMap f=foldr mappend mempty。fmap f
但是,我们可以在foldr
函数中使用f
,如:
foldMap' :: (Foldable f, Monoid m) => (a -> m) -> f a -> m
foldMap' f x = foldr (\y -> mappend (f y)) mempty x
或更短:
foldMap' :: (Foldable f, Monoid m) => (a -> m) -> f a -> m
foldMap' f = foldr (mappend . f) mempty
因此,我们首先用f
对数据结构中的值进行预处理,将其转换为一个monoid对象,并将mappend
称为这些项的折叠函数。因此您有以下签名:foldMap::(monoidm,Foldable f)=>(a->m)->fa m
。让我们一步一步走
制约因素:
Monoid
是可以通过某种操作组合的数据。如果你想一想,你可以得到很多例子。我只想在此提及:
Integer
作为数据,+
作为操作。元素1
和2
可以组合为3=1+2
李>
Integer
作为数据,*
作为操作。元素1
和2
可以组合在一起,给出2=1*2
将
列为数据,++
列为操作。元素[1,2]
和[2,3]
可以组合为[1,2,2,3]=[1,2]+[2,3]
- 大小为2的
向量
作为数据,大小为+
作为操作。元素
和
可以组合为=+
- 等等
以上所有示例都有一个haskell中的幺半群
表示,通常使用newtype
或数据
关键字来定义。在haskell中,幺半群运算表示为
一个重要的性质是幺半群有一个中性元素并且是结合的。在+
下的整数
上下文中,中性元素是0
一个关联性由(a+b)+c=a+(b+c)
这一事实给出。您可以在所有给定的示例中轻松找到这些属性。试试看
可折叠
约束更容易。本质上,您可以将可折叠的数据结构汇总为一个值
函数参数
代码值千言万语,所以
foldMap :: (Monoid m, Foldable f) => (a -> m) -> f a -> m
-- ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^ ^^^
-- |- We've seen this | |
-- | |- A 'Set' of a's which can be collapse into a single value
-- |- A function to convert a's into a monoid
因此,根据定义,您可以很容易地遵循以下推理/算法:
前提
我有一个元素结构,可以折叠成一个值
我有办法把这个元素转换成幺半群的元素
幺半群有一个中性元素
两个幺半群元素可以组合在一起
算法
- 通过使用幺半群算子组合结构的元素来折叠它们
- 如果结构为空,则使用中性元素作为结果
很别致,但是。。。我还是不明白
问题是,当您定义一个可折叠的实例时,您还没有定义如何折叠结构,每个实例的折叠方式都不同!。正如威廉的回答一样,你可以用foldr
来定义foldMap
,这意味着foldr
定义了你可以折叠结构的方式。反之亦然:你可以用foldMap
来定义foldr
,很可能这就是答案!!如果尚未定义foldr
,则没有实现foldMap
的通用方法,这将取决于您的数据结构。因此,作为一个代码集:
class Foldable t where
foldMap :: Monoid m => (a -> m) -> t a -> m -- A default instance can be provided if you define foldr (a.k.a a way to collapse the structure)
foldr :: (a -> b -> b) -> b -> t a -> b -- A default instance can be provided if you define foldMap (a.k.a a way to collapse the structure into a monoid element)
-- but if you don't provide at least one, It'll be impossible to implement any
-- because you aren't telling me how to collapse the structure!!
使用功能a->m
。这有时只是一个id
。您可以在这里将foldMap f
实现为foldr(\x->mappend(f x))mempty
。请注意,Foldable
并不意味着函子
@WillemVanOnsem我尝试了,但我得到了错误(在我的帖子中编辑)。您忘记在签名中添加Foldable
类型约束。非常简洁的解释,感谢您包含foldr的定义