当我尝试使用size (N a (left a) (right a))
而不是size (N a left right)
时,ghci告诉我,定义时此行发生冲突。我不确定为什么,因为在我的数据签名中,它是N a (Tree a) (Tree a)
。 size
是一种用于计算Bin树中节点数的功能。
data Tree a = Nil | N a (Tree a) (Tree a) deriving (Show, Read, Eq)
size :: Tree Int -> Int
size Nil = 0
size (N _ left right) = 1 + size left + size right
答案 0 :(得分:4)
当我尝试调整大小(N a(左a)(右a))而不是大小(N a左右)
left
和right
在这种情况下是类型Tree Int
的表达式。
a
不是已知的变量或类型。
如果定义已更新为size (N a left right)
,则a
是Int
类型的绑定表达式。
答案 1 :(得分:1)
为帮助您了解发生了什么,您可以编写匹配的内部节点,以命名左和右子树及其各自的值,
size (N _ left@(N a _ _) right@(N b _ _)) = 1 + size left + size right
Section 3.17.1 “Patterns”描述了at符号所发生的情况,这些符号使程序员可以命名左右子树。
格式为
var@pat
的模式称为 as-patterns ,并且允许使用 var 作为与匹配的值的名称pat 。
出于多种原因,这种宽泛的方法并不明智。
left
代数数据类型的声明,right
和Tree
已被限制为Tree
类型。size
自变量定义Nil
的其他三种情况。Section 3.17.2 Informal Semantics of Pattern Matching概述了该语言如何处理模式的情况。在这个问题的背景下给您特别注意的是
1。将模式 var 与值 v 匹配总是成功,并将 var 绑定到 v 。
和
5。将模式 con pat 1 …pat n 与值进行匹配,其中 con 是由{{ 1}},具体取决于值:
- 如果值的形式为 con v 1 …v n ,则子模式将与子模式从左到右匹配数据值的组成部分;如果所有比赛均成功,则整体比赛成功;第一次失败或发散会分别导致整体匹配失败或发散。
- 如果值的形式为 con'v 1 …v n ,其中 con 是 con'使用其他构造函数,则匹配失败。
- 如果值为⊥,则匹配发散。
第一个是通过将左右子树绑定到变量来实现它以及如何在问题中编写它。您的第一次尝试似乎有点像绑定到构造函数,这就是为什么您遇到语法错误。
Haskell模式匹配可以更复杂,例如 ,view patterns。对于学习练习,请先掌握基础知识。