我正在关注foldM
以获得如何使用它的直觉.
foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a
在这个简单的例子中,我简单地回来了[Just 100]
.但是,如果我想使用该b
怎么办?
ghci> foldM (\a _ -> return a) (Just 100) [1,2,3] :: [Maybe Int]
[Just 100]
Run Code Online (Sandbox Code Playgroud)
我很困惑如何使用b
内部(a -> b -> m a)
.
请帮助我获得这个功能的直觉以及如何使用b
.
Dan*_*ner 12
这是一个愚蠢的例子.假设我们想要对列表求和,并确保部分总和从未超过(例如)10; 从而:
> let ensure p x = x <$ guard (p x)
> foldM (\a b -> ensure (<10) (a+b)) 0 [1,2,3] :: Maybe Integer
Just 6
> foldM (\a b -> ensure (<10) (a+b)) 0 [5,5,5,-10] :: Maybe Integer
Nothing
Run Code Online (Sandbox Code Playgroud)
我相信你有问题,foldl
而不是foldM
.foldM
基本上只是一个非常小的变化foldl
.
所以考虑:
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f x xs
Run Code Online (Sandbox Code Playgroud)
"发生"的是: - 如果xs == []
那么x
返回.- 否则f
称为:f x (xs !! 0)
获取结果值y :: a
.然后f
被称为:f y (xs !! 1)
,获得z
.然后我们去f z (xs !! 2)
等
正如您所看到的,每次调用f
都会将当前结果传递到该点,并将输入中的下一个元素传递给列表中的下一个元素.因此,只要您想将列表缩减为单个值并且您想要执行的计算是"顺序",即从第一个元素计算值,然后从此值计算值,并使用以下元素计算新值,从这个和第二个元素你计算一个新的等.
例如:
f ys x = map (+x) ys ++ [x]
foldl f [] [1,2,3]
Run Code Online (Sandbox Code Playgroud)
生产:
[6, 5, 3]
Run Code Online (Sandbox Code Playgroud)
因为:
f [] 1 = [1]
f [1] 2 = [1+2, 2] = [3, 2]
f [3, 2] 3 = [3+3, 2+3, 3] = [6, 5, 3]
为了更好地了解foldl
和foldr
工作,请参阅:
现在,foldM
与foldl
现在的f :: a -> b -> a
类型相同f :: a -> b -> m a
.这意味着将当前结果与下一个元素组合在一起的函数是monadic动作,即它可以产生效果.
例如,考虑:
f ys x = do
let a = map (+x) ys ++ [x]
print a
return a
foldM f [] [1,2,3]
Run Code Online (Sandbox Code Playgroud)
会发生什么是文字:
[1]
[3,2]
[6,5,3]
Run Code Online (Sandbox Code Playgroud)
得到打印,值[6, 5, 3]
是monadic动作的返回值.
归档时间: |
|
查看次数: |
2470 次 |
最近记录: |