了解守卫功能和列表理解
Understanding the guard function and list comprehension
我正在从 Miran Lipovaca 的书 'Learn You a Haskell for Great Good!' 中学习 guard
函数。
对于以下示例:
ghci> [1..50] >>= (\x -> guard('7' `elem` show x) >> return x)
[7, 17, 27, 37, 47]
我知道guard
取一个布尔值,如果取值为True
,guard取()
放到一个最小的默认上下文中就成功了。
如果值为 False
,则 guard
会产生一个失败的 monadic 值。
但是,我不明白上面例子中的 guard 如何工作来创建结果列表 [7, 17, 27, 37, 47]
。在 lambda 函数中作为 x
传递的是什么,是 1 吗?此外,如果 ('7' `elem` show x)
的计算结果为 False
,那么不会返回空列表吗?最终的成绩单究竟是如何得出的?
在列表Monad
实例中:
>>=
是 concatMap
,参数翻转后
guard condition
等同于 if condition then [()] else []
并且在任何 Monad
实例中,a >> b
= a >>= \_ -> b
,因此在列表实例中这等同于 concatMap (\_ -> b) a
.
因此您的代码脱糖为:
concatMap
(\x -> concatMap
(\_ -> [x])
(if '7' `elem` show x then [()] else []))
[1..50]
因此外部 concatMap
生成一个包含 50 个元素的列表作为中间值,每个元素都是一个列表,如果其字符串表示形式包含数字 7
,则它是输入值的单例列表,或者空列表:
[[], [], [], [], [], [], [7], [], [], [], [], [], [], [], [], [], [17], …]
然后将其连接起来产生最终结果 [7, 17, 27, 37, 47]
。
What is passed as x in the lambda function, is it 1?
它是输入列表的每个元素,1
到50
。
如果条件为真,内部 concatMap
生成 [x]
,如果条件为假,则生成 []
,因为 guard
生成一个元素列表(虚拟()
) 如果条件为真,如果条件为假则为空列表——如果将其改写为等价物,这可能更容易理解:
map (\_ -> x) (if '7' `elem` show x then [()] else [])
-- or
if '7' `elem` show x then [x] else []
我正在从 Miran Lipovaca 的书 'Learn You a Haskell for Great Good!' 中学习 guard
函数。
对于以下示例:
ghci> [1..50] >>= (\x -> guard('7' `elem` show x) >> return x)
[7, 17, 27, 37, 47]
我知道guard
取一个布尔值,如果取值为True
,guard取()
放到一个最小的默认上下文中就成功了。
如果值为 False
,则 guard
会产生一个失败的 monadic 值。
但是,我不明白上面例子中的 guard 如何工作来创建结果列表 [7, 17, 27, 37, 47]
。在 lambda 函数中作为 x
传递的是什么,是 1 吗?此外,如果 ('7' `elem` show x)
的计算结果为 False
,那么不会返回空列表吗?最终的成绩单究竟是如何得出的?
在列表Monad
实例中:
>>=
是concatMap
,参数翻转后guard condition
等同于if condition then [()] else []
并且在任何 Monad
实例中,a >> b
= a >>= \_ -> b
,因此在列表实例中这等同于 concatMap (\_ -> b) a
.
因此您的代码脱糖为:
concatMap
(\x -> concatMap
(\_ -> [x])
(if '7' `elem` show x then [()] else []))
[1..50]
因此外部 concatMap
生成一个包含 50 个元素的列表作为中间值,每个元素都是一个列表,如果其字符串表示形式包含数字 7
,则它是输入值的单例列表,或者空列表:
[[], [], [], [], [], [], [7], [], [], [], [], [], [], [], [], [], [17], …]
然后将其连接起来产生最终结果 [7, 17, 27, 37, 47]
。
What is passed as x in the lambda function, is it 1?
它是输入列表的每个元素,1
到50
。
如果条件为真,内部 concatMap
生成 [x]
,如果条件为假,则生成 []
,因为 guard
生成一个元素列表(虚拟()
) 如果条件为真,如果条件为假则为空列表——如果将其改写为等价物,这可能更容易理解:
map (\_ -> x) (if '7' `elem` show x then [()] else [])
-- or
if '7' `elem` show x then [x] else []