Reputation: 139
When i tried to size (N a (left a) (right a))
instead of size (N a left right)
, i was told by ghci that this line conflicts when the definition. I am not sure why because in my data signature, it is N a (Tree a) (Tree a)
. size
is a function to count the number of nodes in a bin tree.
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
Upvotes: 1
Views: 184
Reputation: 139711
To help you see what’s going on, you could write your match internal nodes to name the left and right subtrees and their respective values with
size (N _ left@(N a _ _) right@(N b _ _)) = 1 + size left + size right
Section 3.17.1 “Patterns” describes what is happening with the at signs, which allow the programmer to name the left and right subtrees.
Patterns of the form
var@pat
are called as-patterns, and allow one to use var as a name for the value being matched by pat.
The broad approach is inelegant for a number of reasons.
left
and right
are already constrained to be of type Tree
because of the declaration of the Tree
algebraic datatype.size
for either one or two Nil
arguments.Section 3.17.2 Informal Semantics of Pattern Matching outlines the cases for how the language handles patterns. Of especial note to you in the context of this question are
1. Matching the pattern var against a value v always succeeds and binds var to v.
and
5. Matching the pattern con pat1 … patn against a value, where con is a constructor defined by
data
, depends on the value:
- If the value is of the form con v1 … vn, sub-patterns are matched left-to-right against the components of the data value; if all matches succeed, the overall match succeeds; the first to fail or diverge causes the overall match to fail or diverge, respectively.
- If the value is of the form con′ v1 … vn, where con is a different constructor to con′, the match fails.
- If the value is ⊥, the match diverges.
The first is how you want to do it and how you wrote it in your question, by binding the left and right subtree to variables. Your first attempt looked vaguely like binding to a constructor, and that’s why you got a syntax error.
Haskell pattern matching can be more sophisticated, e.g., view patterns. For learning exercises, master the basics first.
Upvotes: 1
Reputation: 22000
When i tried to size (N a (left a) (right a)) instead of size (N a left right)
left
and right
in this case are expressions of type Tree Int
.
a
is not a known variable or type in this context.
In case the definition is updated to size (N a left right)
, then a
is a bound expression of type Int
.
Upvotes: 4