【问题标题】:Understanding the guard function and list comprehension理解守卫功能和列表理解
【发布时间】:2019-08-05 00:24:28
【问题描述】:

我正在从“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 生成一个失败的一元值。

但是,我不明白在上面的示例中,guard 如何创建结果列表[7, 17, 27, 37, 47]。在 lambda 函数中作为 x 传递的内容是 1 吗?此外,如果('7' `elem` show x) 的计算结果为False,那么不会返回空列表吗?最终的结果列表到底是怎么来的?

【问题讨论】:

    标签: list haskell list-comprehension monads guard-statement


    【解决方案1】:

    列表中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]

    在 lambda 函数中作为 x 传递的是什么,是 1 吗?

    它是输入列表的每个元素,150

    如果条件为真,则内部concatMap 产生[x],如果条件为假,则产生[],因为如果条件为真,guard 产生一个包含一个元素的列表(虚拟())并且如果为 false,则为空列表——如果您将其重新表述为等效项,则可能更容易看出:

    map (\_ -> x) (if '7' `elem` show x then [()] else [])
    -- or
    if '7' `elem` show x then [x] else []
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-19
      • 2017-01-08
      • 1970-01-01
      • 2019-09-20
      • 2011-08-05
      相关资源
      最近更新 更多