【问题标题】:Pattern matching inside lambdalambda 内部的模式匹配
【发布时间】:2016-11-27 20:33:32
【问题描述】:

我正在学习 Haskell。这是一个简单的示例,但我想了解为什么我不能在以下示例中使用 lambda 函数内部的模式匹配的概念(即,为什么 filterfold' 函数运行但 filterfold' 给出运行时错误):

-- Runs
filterfold' :: (a -> Bool) -> [a] -> [a]
filterfold' p zs = foldr (\y zs -> if (p y) then y:zs else zs) [] zs

-- Runtime error: Non-exhaustive patterns in lambda
filterfold :: (a -> Bool) -> [a] -> [a]
filterfold p (z:zs) = foldr (\y (z:zs) -> if (p y) then y:(z:zs) else (z:zs)) [] (z:zs)

【问题讨论】:

    标签: haskell lambda pattern-matching


    【解决方案1】:

    您可以使用它,但编译器会告诉您缺少一个案例(当输入为 [] 时)

    如果你说z:zs,它会尝试将此模式与输入列表匹配 - 如果你

    • 输入[1,2,3] = 1:[2,3]你得到z=1zs=[2,3]
    • 但当输入[] 时,您无法获得zzs,因此z:zs = [](从技术上讲,它们基于列表数据类型的不同构造函数)

    所以在运行时,当它看到[] 并抛出异常时,它将不知道如何处理这种情况/模式。

    如果您仔细查看您的示例,您应该会发现您实际上从未使用过这些部件(意思是 zzs - 您只能再次将它们用作 z:zs)所以我无法告诉您如何操作更好

    无论如何,您都可以在 lambda 中使用 case - 表达式:

    ... = foldr (\ x zs -> case zs of
                             [] -> ...
                             z:zs -> ...
    

    或者您可以使用LambdaCase 扩展名使其更短。

    【讨论】:

    • 所以,来自 filterfold 函数参数的 zs 在范围内,但它没有使用来自 filterfold 的 'z',而是尝试在 lambda 内部执行模式匹配?
    • 是的,lambda 中的zzs 将是不同的(foldr提供它们) - 这就是为什么你不应该重用参数/参数名称对于 lambda-arguments - 你 introduce 这些名称与你的 lambda 并将隐藏一次从外部范围 - 所以如果你想(重新)使用 zzs 从外部-scope in filterfold 你应该把它重命名为foldr (\y ys -> ...) (或者你喜欢的任何名称,不同于pzzsy;))
    • 但请注意:如果您实际上不需要提供给foldr 的函数的第二个参数(lambda),那么您可能首先不需要foldr因为您仅在列表的 head 不为空或默认为 foldr 的第二个参数时才对它进行操作
    • 了解 filterfold' 是比 filterfold 更干净的版本。这只是为了概念上的理解。因此,在 filterfold' 中,我可以将 foldr 的 lambda 函数定义为具有不同参数名称的 (\y qs -> if (p y) then y:qs else qs)。我知道 lambda 中的 y 参数将是列表“zs”中的当前元素。但是什么是qs?为什么和zs列表一样?
    • 您可以将qs 视为您传递的累加器或状态 - 因此您从输入列表的右端开始并将[] 替换为@987654354 的第二个参数@(这里也是 '[]`)- 然后你取最后一个元素 yqs=[] 并将它们与你的 lambda 组合成一个新的 qs ... 对列表中的第一个元素重复此操作
    猜你喜欢
    • 2018-03-30
    • 2019-01-13
    • 2023-01-13
    • 1970-01-01
    • 2015-04-25
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多