I am trying to understand the code found here. I am an OCaml person and not a Haskeller.
The author defines the following algebraic data type and some relevant functions — the details of which do not really matter.
data Node k v
= Node { nKey :: k
, nValue :: v
, nSibling :: Node k v
, nChild :: Node k v }
| Head { nSibling :: Node k v
, nChild :: Node k v }
| Nil
nodeLTKey :: forall k v. Ord k => Node k v -> k -> Bool
nodeEQKey :: forall k v. Eq k => Node k v -> k -> Bool
sibling :: forall k v. Node k v -> Node k v
Later in the insert
function around line 113, they define a helper function of type Node k v -> (Node k v, Int)
. I have extracted the part I am confused about below.
go Nil = (Nil, wins)
go n
| nodeLTKey sN k = (n {nSibling = fst $ go sN}, -1)
| nodeEQKey sN k = (n {nSibling = sN {nValue = v}}, -1)
-- how can they update the inner record?
where
sN = sibling n
-- How can the compiler be sure that sN is a Node and not Head / Nil?
The sibling
function returns a Node k v
and only one of the possible variants of a Node k v
actually has a field called nValue
. I don’t understand how the second guard can be sure that sN
will have an nValue
field — i.e that sN
will be of the Node
case and not Head
/ Nil
.