The dflemstr answer is in place, but I thought I would add two comments (which may not be satisfied with the comment on the original answer).
Firstly, by the same logic that the second definition can save memory, a similar argument can be made for this:
data Tree a = Empty | Leaf a | LeftOnly a (Tree a) | RightOnly a (Tree a) | Branch a (Tree a) (Tree a)
It doesn't matter if it depends on your application.
A second and more important point is that if you avoid using data constructors directly, you can ignore these implementations. For example, equivalent foldTree functions can be written for any of these types. For a shorter type, you do it like this:
data Tree a = Empty | Node a (Tree a) (Tree a) foldTree :: (a -> b -> b -> b) -> b -> Tree a -> b foldTree fz Empty = z foldTree fz (Node vlr) = fv (subfold l) (subfold r) where subfold = foldTree fz
And for a longer one, you can write this as follows:
data Tree a = Empty | Leaf a | Node a (Tree a) (Tree a) foldTree :: (a -> b -> b -> b) -> b -> Tree a -> b foldTree fz Empty = z foldTree fz (Leaf v) = fvzz foldTree fz (Node vlr) = fv (subfold l) (subfold r) where subfold = foldTree fz
The same can be done for your Maybe alternative or for my alternative with five constructors. In addition, this method can be applied to all other common tree functions that you need. (In fact, many of these functions can be written in foldTree terms, so most of them fall foldTree definitions above.)
source share