I have type
data EvalATree b a = Leaf a | Node ([b] -> a) [EvalATree b a]
I have written Show and Foldable instances, 'Edited:' taking that a = b
instance (Show a, Show a) => Show (EvalATree a a) where
show :: (Show a, Show a) => EvalATree a a -> String
show (Leaf a) = "Leaf " ++ show a
show (Node g trees) = "Node " ++ show (calcNode (Node g trees)) ++ " " ++ show trees
instance Foldable (EvalATree a) where
foldr f z (Leaf x) = f x z
foldr f z (Node func subtrees) = foldr (\subtree acc -> foldr f acc subtree) z subtrees
Problem
I can't realize how to write Read instance. Functions for Node are just names, which means i have to take functions from dictionary, and i can't do this either.
example of tree string
let tree = Node someFunction [Leaf 1, Leaf 2, Leaf 3]
let treeStr = "Node someFunction [Leaf 1, Leaf 2, Leaf 3]"
I tried writing parsers.
parseEvalATree :: (Read a, Read a) => Parser a -> Parser (EvalATree a a)
parseEvalATree parserA = parseLeaf parserA <|> parseNode intFunctionDict parserA
parseLeaf :: (Read a, Read a) => Parser a -> Parser (EvalATree a a)
parseLeaf parserA = Leaf <$> parserA
parseNode :: (Read a, Read a) => Map String ([a] -> a) -> Parser a -> Parser (EvalATree a a)
parseNode dict parserA = do
string "Node"
spaces
funcName <- many1 letter
spaces
subtrees <- between (char '[') (char ']') (parseEvalATree parserA `sepBy` char ',')
let func = case Map.lookup funcName dict of
Just f -> f
Nothing -> error "Function not defined"
return (Node func subtrees)
But i couldn't apply them.
We only really need to identify "Leaf" or "Node something" and then defer to the Read instance of the element type for the rest.
Something like this might be good enough.
I've assumed
lookupFuncwith a type likeString -> Maybe ([a] -> a)to look up the function names. But this type will only allow for functions likeheadthat work on any[a]. You probably want to allow functions likesumthat will work on particular element types. So function lookup needs to be in a class.And add the Funcs constraint like
Final note: if you do want to use parser combinators, Text.ParserCombinators.ReadP (in base) has
readS_to_Pwhich lets you easily use Read instances as part of parsers. I'm not sure if other parser libraries have an equivalent.