考虑以下签名 foldMap
foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
Run Code Online (Sandbox Code Playgroud)
这与"绑定"非常相似,只是交换了参数:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
在我看来,有因此必须有某种关系的Foldable,Monoid和Monad,但在超我找不到它.据推测,我可以将其中的一个或两个转换为另一个,但我不确定如何.
这种关系可以详细说明吗?
我是Haskell的初学者,并且从"了解你一个Haskell"中学到了一些我对Foldable的Tree实现不了解的东西.
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
Run Code Online (Sandbox Code Playgroud)
引用来自:LYOH:"因此,如果我们只为某种类型实现foldMap,我们可以免费获得该类型的foldr和foldl!"
有人可以解释一下吗?我不明白为什么以及如何免费获得foldr和foldl ..
data Tree t = Empty | Node t (Tree t) (Tree t)
Run Code Online (Sandbox Code Playgroud)
我们可以创建Functor实例并使用
fmap :: (t -> a) -> Tree t -> Tree a
Run Code Online (Sandbox Code Playgroud)
但是如果不是(t - > a)我想要(树t - > a)那么我可以访问整个(节点t)而不仅仅是t
treeMap :: (Tree t -> a) -> Tree t -> Tree a
treeMap f Empty = Empty
treeMap f n@(Node _ l r) = Node (f n) (treeMap f l) (treeMap f r)
Run Code Online (Sandbox Code Playgroud)
与折叠相同
treeFold :: (Tree t -> a -> a) -> a -> Tree t -> a …Run Code Online (Sandbox Code Playgroud) 在Applicative深入研究的同时,我来到了Traversable.虽然我已经Foldable从LYHGG知道了,但我还没有见过前者,所以我开始阅读关于Traversable的Haskell wiki.
在阅读它时,我理解为什么它Foldable.fold是平行的Traversable.sequenceA并且Foldable.foldMap是平行的Traversable.traverse.
我也看到每个Traversable也是a Foldable和a Functor,sequenceA并且traversal彼此有默认实现:
traverse f = sequenceA . fmap f
sequenceA = traverse id
Run Code Online (Sandbox Code Playgroud)
所以,正如我在LYHGG中看到的那样,它foldMap是一个最小的完整定义Foldable,我认为,它是平行的traverse,所以fold(它是平行的sequenceA)也是一个最小的完整定义(它不是)... Foldable是不是Functor喜欢Traversable的,所以我们不能申请这个:
foldMap f = fold . fmap f
fold = foldMap id -- this is ok
Run Code Online (Sandbox Code Playgroud)
为什么不是每Foldable一个 …
我正在玩类型对齐的序列,特别是我正在搞乱折叠它们的想法.可折叠的类型对齐序列看起来像这样:
class FoldableTA fm where
foldMapTA :: Category h =>
(forall b c . a b c -> h b c) ->
fm a b d -> h b d
foldrTA :: (forall b c d . a c d -> h b c -> h b d) ->
h p q -> fm a q r -> h p r
foldlTA :: ...
Run Code Online (Sandbox Code Playgroud)
通过首先使用以天真的方式将序列转换为类型对齐的列表(即,使用类型对齐的列表类别)然后折叠该列表,实现foldrTA起来非常容易.不幸的是,这可能是非常低效的,因为长列表可以预先设置为短列表.我一直试图找出一种方法来使用类似于用于更有效地定义右和左折叠的技巧,但这些类型让我头晕目眩.这似乎不够通用,我从其他方向采取的每一步都会让我得到更多的类型变量,而不是我能追踪到的.foldMapTAfoldMapTAData.FoldableEndo
我们知道,fmap是fmap :: Functor f => (a -> b) -> f a -> f b和sum是sum :: (Num a, Foldable t) => t a -> a,但下面的代码让我困惑.
> :t (fmap sum Just)
(fmap sum Just) :: Num b => b -> b
> fmap sum Just 3
3
Run Code Online (Sandbox Code Playgroud)
为什么?
class (Functor t, Foldable t) => Traversable t where
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
traverse g = sequenceA . fmap g
sequenceA :: Applicative f => t (f a) -> f (t a)
sequenceA = traverse id
Run Code Online (Sandbox Code Playgroud)
它如何Traversable同时使用Foldable和继承子类的事实Functor?
t如果是可遍历类型,t则它也意味着函子类型和可折叠类型。
我看到的事实t是一个仿函数类型,即fmap,在使用traverse。
是在t某处使用的可折叠类型的事实吗?
是否traverse使用t可折叠类型的事实?
使用哪个事实sequenceA:t是仿函数类型,t …
我对矩阵列表求和,foldl1 (+)因为我注意到sum实际上返回的是左上角元素的和为1x1矩阵。
$ stack exec --resolver lts-12.5 --package matrix -- ghci
GHCi, version 8.4.3: http://www.haskell.org/ghc/ :? for help
Prelude> import Data.Matrix
Prelude Data.Matrix> t = [identity 2, identity 2] -- two 2x2 identity matrices
Prelude Data.Matrix> foldl1 (+) t
? ?
? 2 0 ?
? 0 2 ?
? ?
Prelude Data.Matrix> sum t
? ?
? 2 ?
? ?
Run Code Online (Sandbox Code Playgroud)
这对我来说是出乎意料的,LYAH建议sum = foldl1 (+)¹甚至hlint建议我使用sum而不是foldl1 (+)' Removing error on …
我刚刚开始学习Haskell。据我所知,maximum给出了整数列表的最大值。因此,maximum [2,5,7,1]给出7。但是为什么通过给出元组输入,max总是给出第二个元素?例如,maximum (8,1)给1同样的事情发生的sum (8,1),product (5,2),minimum (4,5)...所有给出的元组的第二个元素。因此,有人可以向初学者解释为什么会发生这种情况吗?
在查看Monoid我的定义时,我注意到mconcat具有以下定义(源):
mconcat :: Monoid a => [a] -> a
mconcat = foldr mappend mempty
Run Code Online (Sandbox Code Playgroud)
为什么签名将其限制为[a]而不是Foldable像这样更通用?
mconcat' :: (Foldable t, Monoid a) => t a -> a
mconcat' = foldr mappend mempty
Run Code Online (Sandbox Code Playgroud)
这是历史原因吗?或者这种更通用的实现是否会使特定类型更难提供它的优化版本,例如[]使用列表理解(source)的情况?