First of all the data type definition should not contain question marks, but normal letters:
data Tree a = Leaf a | Fork a (Tree a) (Tree a)
It defines a type Tree
that contains elements of some not further specified type a
.
The tree is either a Leaf
, containing an element of type a
, or it is a Fork
, containing also an element of type a
and two subtrees. The subtrees are Tree
structures that contain elements of type a
.
Important to note is that Haskell uses parenthesis purely for grouping, like in 2 * (2+3)
, not to specify calling functions. To call functions, the parameters are just written after the function name, separated with spaces, like in sin 30
or compare "abc" "abd"
.
In the case
statement, the part to the left of ->
is a pattern match, the part to the right is the functions result in case the tree actually had the form specified on the left. The pattern Fork q (Fork p a b) c
matches if the tree is a Fork
(that's the Fork
from the data type definition) and the first subtree of it is another Fork
. The lowercase letters are all just variables, capturing the different parts of the tree structure matched. So p
would be the element contained in the subtree, a
would be the subtrees first branch and b
the second one.
The right side of the ->
, Fork p a (Fork q b c)
, now builds a new tree from these parts matched in the pattern match. The lower case variables are all the tree parts matched on the left, and the Fork
s are the constructors from the data type definition. It build a tree that is a Fork
and has a second subtree that is also a Fork
(the part in parenthesis). The remaining pieces of this tree are just the parts of the tree that has been "dissolved" on the left side.