As Willem says, you can derive Read
to get this function for free:
data Letter = A | B | C | D | E | F | G
deriving (Show, Eq, Enum, Bounded, Read)
data BinaryTree a = Leaf a | Branch (BinaryTree a) (BinaryTree a)
deriving (Eq, Show, Read)
t :: BinaryTree Letter
t = Branch (Leaf A) (Branch (Branch (Leaf A) (Leaf C)) (Leaf D))
Trying this:
λ> t == read (show t)
True
create the tree else return "" for failed parsing all without deriving (Show, Read)
.
parseTree = do{ item; symb "Leaf"; ... +++ ... }
I'm not sure what "" means in the context of reading a binary tree from a string: According to your definition of binary tree, trees cannot be empty, since even Leaf
contains at least one letter. So maybe you're looking for a function String -> Maybe (BinaryTree Letter)
.
Since your reluctance to use derived Show
and Read
instances, this must be an exercise in writing a parser. You could structure a recursive-descent parser in the following way:
parseLetter :: String -> Maybe (Letter, String)
parseLetter s = ...
parseTree :: String -> Maybe (BinaryTree Letter, String)
parseTree s
| "Leaf " `isPrefixOf` s = ...
| "Branch " `isPrefixOf` s = ...
| otherwise = Nothing
Here the (..., String)
is the left-over of the string being parsed that isn't consumed by a sub-parser. E.g. in parsing Branch (Leaf A) (Leaf B)
, when parseLetter
has parsed A
, it may return (A, ") (Leaf B)")
for its caller.
Note, however, that getting something of comparable quality to deriving Read
requires being pretty flexible with regards to whitespace and parentheses:
λ> read "Branch ( Leaf A)( Branch ( Leaf B ) ((Leaf C) ) ) " :: BinaryTree Letter
Branch (Leaf A) (Branch (Leaf B) (Leaf C))
I am unsure how I would handle the case of going through a leaf or branch
Going through a leaf means parsing a single letter.
Going through a branch means calling upon the parser recursively.
You may want to use a more efficient and ergonomic parsing library, like what Text.Read
exposes (it even contains an example of reading a tree type), or you might want to use a parser combinator framework like Megaparsec or ReadP.
deriving (Show, Read)
in yourdata BinaryTree
, and thne it will make a parser itself. - Willem Van Onsemreturn (Branch x y)
for example. - Willem Van Onsem