we have introduced monoids before, and in this post, we will continue to examine the usage of monoids, we will continue this post with introduction on the some datascture implemented with monoids, such as tree....
in this post we will discuss something that is related to the Monoid with the fold data structure.
One of the more interesting ways to put monoids to work is to make them help us define folds over various data structures.
Fold can work over alomst any data structure, Trees especially lend themeselves well to folding.
In fact, there is a Foldable type class was introduced.
to use that, you can do like this:
import qualified Foldable as F
function that may comes handy are included as follow.
foldr, foldl, foldr1 and foldl1
let's compare the Prelude.Foldr and hte Foldable.foldr,
ghci> :t foldr foldr :: (a -> b -> b) -> b -> [a] -> b ghci> :t F.foldr F.foldr :: (F.Foldable t) => (a -> b -> b) -> b -> t a -> b
as you can see that the foldr in the Prelude is used for the list type, while the foldr is used for almost any types.
some of the test comparision of the two is like this:
ghci> foldr (*) 1 [1,2,3]
6
ghci> F.foldr (*) 1 [1,2,3]
6
ghci> F.foldl (+) 2 (Just 9)
11
ghci> F.foldr (||) False (Just True)
True
Now let's make some type part of the Foldable, so that we can do foldx on the customized types. remember the types that we have showed before like this:
data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)
suppose that we are going to make a visiting procedure that visit the tree, here is the code.
before going to the real code, we will first visit the code which we will use to help us.. It is the FlatMap method.
foldMap :: (Monoid m, Foldable t) => (a -> m) -> t a -> mthis is a function which takes as its first parameter of the type that our foldable stucture contains, and returns a monoid,. and the second type is a foldable structure that contains values of type a. It maps that function over the foldable structure, thus producing a foldable structure that contains monoid values. Then, by doing mappend between those monoid values, it joins them all into a single monoid value.
instance F.Foldable Tree where
foldMap f Empty = mempty
foldMap f (Node x l r) = F.foldMap f l `mappend`
f x `mappend`
F.foldMap f r
testTree = Node 5
(Node 3
(Node 1 Empty Empty)
(Node 6 Empty Empty)
)
(Node 9
(Node 8 Empty Empty)
(Node 10 Empty Empty)
)
so the following will show what you can do with it..-- to sum ghci> F.foldl (+) 0 testTree 42 -- to foldr and apply product ghci> F.foldl (*) 1 testTree 64800 -- if there is any element that has value of 3 ghci> getAny $ F.foldMap (\x -> Any $ x == 3) testTree True -- list is monoid, so you can visit the tree and get the element along the tree. ghci> F.foldMap (\x -> [x]) testTree [1,3,6,5,8,9,10]
本文探讨了Monoid和Foldable类型类在函数式编程中的应用,特别是如何使用Monoid来辅助定义各种数据结构上的折叠操作。通过实例展示了在自定义类型上实现Foldable实例的过程,并演示了如何对树状数据结构进行求和、乘积等操作。
993

被折叠的 条评论
为什么被折叠?



