- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
考虑
filterM (\x -> [True, False]) [1, 2, 3]
我就是无法理解 Haskell 对此的魔力 filterM
用例。该函数的源码如下:
filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
filterM _ [] = return []
filterM p (x:xs) = do
flg <- p x
ys <- filterM p xs
return (if flg then x:ys else ys)
通过此用例,p
应该是 lambda 函数 (\x -> [True, False])
,第一个 x
应该是1
。那么 flg <- p x
是什么呢?返回? flg
的值到底是多少?对于每个递归?
最佳答案
列表单子(monad) []
模型非确定性:值列表 [a]
代表 a
值的多种不同可能性.
当您看到类似 flg <- p x
的语句时在单子(monad)列表中,flg
将采用 p x
的每个值依次,即True
然后False
在这种情况下。 filterM
的其余部分然后执行两次,对 flg
的每个值执行一次.
要更详细地了解这是如何发生的,您需要了解 do
的脱糖。 (>>=)
的表示法和实现列表单子(monad)的运算符。
do
符号在对 (>>=)
的调用中逐行脱糖。运算符(operator)。例如非空filterM
的正文案例变成
p x >>= \flg -> (filterM p xs >>= \ys -> return (if flg then x:ys else ys))
这完全是机械的,因为它本质上只是替换 flg <-
在 >>= \flg ->
表达式之前表达后。实际上,模式匹配使事情变得更复杂一些,但也不是太复杂。
接下来是(>>=)
的实际实现,它是 Monad
的成员类型类,并且每个实例都有不同的实现。对于 []
,类型为:
(>>=) :: [a] -> (a -> [b]) -> [b]
其实现类似于
[] >>= f = []
(x:xs) >>= f = f x ++ (xs >>= f)
所以循环发生在 (>>=)
的主体中。这一切都在一个库中,除了 do
的脱糖之外没有任何编译器魔法。符号。
(>>=)
的等效定义是
xs >>= f = concat (map f xs)
这也可以帮助您了解正在发生的情况。
对于 filterM
的递归调用也会发生同样的事情:对于 flg
的每个值,进行递归调用并生成结果列表,最终 return
对每个元素 ys
执行语句在此结果列表中。
每次递归调用的这种“扇出”都会导致 2^3 = 8
最终结果 filterM (\x -> [True, False]) [1, 2, 3]
中的元素.
关于haskell - 了解filterM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28872396/
我试图通过附加一个数字来查找目录名称,直到找到一个尚不存在的名称: head filterM (fmap not . fexists_) [ getDatedDir t d n | n >= \ca
我目前正在通过在 python 中编写一个 monad 库来自学函数式编程。而且我在类型提示方面遇到了麻烦。例如,Haskell 中有一个带有签名的函数 filterM filterM :: (a -
我对Haskell优化在内部的工作方式不太了解,但我一直在使用过滤器,希望它们可以被优化为等效于C++的简单过滤器。例如 mapM_ print $ filter (\n -> n `mod` 2 =
简而言之:您将如何过滤 Map 的元素? , 或 Set在单子(monad)上 Haskell中的谓词? 我可以想到两种可能的方法: a) 通过列表和 filterM 往返(可能效率不高): filt
我是一名优秀的程序员,十分优秀!