代码之家  ›  专栏  ›  技术社区  ›  Addem

与防护装置匹配的haskell图案

  •  0
  • Addem  · 技术社区  · 7 年前

    假设我想用

    data Tree = Null | Node Tree Integer Tree deriving Show
    

    我想测试一下每一个条目,比如说,是否少于10个。我想我会用模式匹配和写

    isSmall :: Tree -> Bool
    isSmall _ 
      | Null = True
      | (Node a b c) = if b >= 10
                       then False
                       else isSmall a && isSmall c
    

    但是它给出了关于 a , b c 超出范围。我本以为把它们放在警卫室里基本上就能把它们放在瞄准镜里。这不是你在哈斯克尔应该怎么做模式匹配吗?我环顾四周寻找可以指导我的示例,但是我没有在使用由其他几个数据结构组成的数据结构的保护中发现任何模式匹配的示例。

    错误:

    test.hs:24:6: Not in scope: data constructor ‘Node’
    
    test.hs:24:11: Not in scope: ‘a’
    
    test.hs:24:13: Not in scope: ‘b’
    
    test.hs:24:15: Not in scope: ‘c’
    
    test.hs:24:27: Not in scope: ‘b’
    
    test.hs:26:38: Not in scope: ‘a’
    
    test.hs:26:57: Not in scope: ‘c’
    
    2 回复  |  直到 7 年前
        1
  •  7
  •   melpomene    7 年前

    这不是你在哈斯克尔应该怎么做模式匹配吗?

    不。保护是布尔表达式,不是模式。

    您可以这样做模式匹配:

    isSmall :: Tree -> Bool
    isSmall Null = True
    isSmall (Node a b c) = b < 10 && isSmall a && isSmall c
    

    …或者像这样:

    isSmall :: Tree -> Bool
    isSmall x = case x of
      Null -> True
      Node a b c -> b < 10 && isSmall a && isSmall c
    

    …或者像这样:

    {-# LANGUAGE LambdaCase #-}
    
    isSmall :: Tree -> Bool
    isSmall = \case
      Null -> True
      Node a b c -> b < 10 && isSmall a && isSmall c
    

    (使用 LambdaCase 语言扩展)。这可能最接近您最初的尝试。

    也就是说,通过使用 <- . 这被称为“图案卫士”:

    isSmall :: Tree -> Bool
    isSmall x 
      | Null <- x = True
      | Node a b c <- x = b < 10 && isSmall a && isSmall c
    

    然而,这种语法在这里并不能给您带来什么好处。你还是要给论点起个名字( x 在这种情况下),你必须明确地说 <- x 到处都是。直接使用模式匹配(使用 case 或多功能方程)。

        2
  •  2
  •   dopamane    7 年前

    如注释所示,这是不正确的模式匹配。以下是实现您所期望的目标的一种方法:

    isSmall :: Tree -> Bool
    isSmall Null         = True
    isSmall (Node a b c) = if b >= 10
                           then False
                           else isSmall a && isSmall c
    

    通过按您在问题中发布的方式进行操作,您还会得到另一个错误:

    * Couldn't match expected type `Bool' with actual type `Tree'
    * In the expression: (Node a b c)
      In a stmt of a pattern guard for
                     an equation for `isSmall':
        (Node a b c)
      In an equation for `isSmall':
          isSmall _
            | Null = True
            | (Node a b c) = if b >= 10 then False else isSmall a && isSmall c
    

    这表示guard语句中的表达式必须是类型 Bool 但你提供了 Tree (或 Null Node )

    推荐文章