Haskell模式与警卫匹配

Add*_*dem 0 haskell pattern-matching guard-clause

假设我想在Haskell中建模树结构

data Tree = Null | Node Tree Integer Tree deriving Show
Run Code Online (Sandbox Code Playgroud)

我想测试每个条目是否小于10.我想我会使用模式匹配和写入

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

然而,它提供了有关的错误a,bc被淘汰的范围.我本以为把他们放在守卫里基本上会把他们放在范围内.这不是你应该如何在Haskell中进行模式匹配吗?我四处寻找可以指导我的示例,但我没有在使用由其他几种数据结构组成的数据结构的警卫中找到任何模式匹配的示例.

错误:

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’
Run Code Online (Sandbox Code Playgroud)

mel*_*ene 7

这不是你应该如何在Haskell中进行模式匹配吗?

防护是布尔表达式,而不是模式.

您可以像这样进行模式匹配:

isSmall :: Tree -> Bool
isSmall Null = True
isSmall (Node a b c) = b < 10 && isSmall a && isSmall c
Run Code Online (Sandbox Code Playgroud)

......或者像这样:

isSmall :: Tree -> Bool
isSmall x = case x of
  Null -> True
  Node a b c -> b < 10 && isSmall a && isSmall c
Run Code Online (Sandbox Code Playgroud)

......甚至是这样的:

{-# LANGUAGE LambdaCase #-}

isSmall :: Tree -> Bool
isSmall = \case
  Null -> True
  Node a b c -> b < 10 && isSmall a && isSmall c
Run Code Online (Sandbox Code Playgroud)

(使用LambdaCase语言扩展).这可能与您原来的尝试最接近.

也就是说,可以通过使用嵌入防护模式<-.这被称为"模式守卫":

isSmall :: Tree -> Bool
isSmall x 
  | Null <- x = True
  | Node a b c <- x = b < 10 && isSmall a && isSmall c
Run Code Online (Sandbox Code Playgroud)

但是,这种语法在这里不会给你太多.你仍然必须给参数一个名字(x在这种情况下),你必须明确地说<- x到处都是.直接使用模式匹配(使用case或多个函数方程)会更清楚.