Hi All,
I thought I was starting to get my head around the whole tying the knot
phenomenon, but when my program produced "*** Exception: <<loop>>" I
figured I was probably missing something :).
Here's what I'm trying to do (I know I could do it without tying the knot,
but that seemed like a reasonable approach and I wanted to get my hands
dirty or feat wet):
I'm reading in a file; that is I have a function String ->
MyDataType. More specifically I'm reading in a Tree, and the tree is
specified in the file with these "Subtree" fields. So you can be reading
along in the tree and then instead of actually seeing a branch or leaf,
you'll see somethign like "[S1]" which means "stick subtree S1 in
here". later in the file (arbitrarily later), you will see something like
"Subtree [S1]" and then following that is that tree.
So what I did was I changed my function to a String -> [(String,Tree)] ->
(Tree, [(String,Tree)] function where the list is a lookup for the
subtrees. I then said:
readTrees s = let (t, st) = readTrees' s st in t
and then the readTrees' basically read the tree in as normal; except when
it gets to something like "[S1]" it does lookup "[S1]" subTrees to get the
subtree and then when it gets to "Subtree [S1]" it reads in the subtree
and then adds it to the subtree list.
Is this not an appropriate use of tying the knot or amd I just doing
something wrong? I've attached my code if you want to read it; It's
marginally more complex that I've written here jsut because of some of the
idiosyncracies in the file format...
- Hal
--
Hal Daume III
"Computer science is no more about computers | [EMAIL PROTECTED]
than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume
module DecisionTree
where
import IO
import List
data DecisionTree
= Test String String String DecisionTree DecisionTree
| Value String Double Double
deriving (Show, Eq, Ord, Read)
readDecisionTree :: String -> DecisionTree
readDecisionTree s =
let (_, wholeTree, subTrees) = readDecisionTree' False subTrees (filter (/=[])
(lines s))
in wholeTree
readDecisionTree' :: Bool -> [(String,DecisionTree)] -> [String] -> ([String],
DecisionTree, [(String,DecisionTree)])
readDecisionTree' _ subTrees [] = ([], Value "" 0 0, subTrees)
readDecisionTree' areValue subTrees (x:xs) =
let (lineDepth, lineType, values') = readLine x
subTreesX = if xs /= [] && "Subtree" `isPrefixOf` head xs
then readSubTrees subTrees xs
else subTrees
(xs', lhs, subTrees') = readDecisionTree' False subTreesX xs
(xs'' , rhs, subTrees'') = readDecisionTree' False subTrees' xs'
(xs''', other, subTrees''') = readDecisionTree' True subTreesX xs
values = values' ++ ["0.0"]
in if lineType -- are we a value
then if areValue
then (xs, Value (values !! 3) (read (values !! 4)) (read (values
!! 5)), subTreesX)
else (xs''', Test (values !! 0) (values !! 1) (values !! 2)
(Value (values !! 3) (read (values !! 4)) (read
(values !! 5)))
other,
subTrees''')
else if '[' == head (last values') -- are we a subtree?
then case lookup (last values') subTreesX of
Nothing -> error "could not find subtree"
Just dt -> (xs'', Test (values !! 0) (values !! 1) (values !!
2) dt lhs, subTrees')
else (xs'', Test (values !! 0) (values !! 1) (values !! 2) lhs rhs,
subTrees'')
readSubTrees subTrees [] = subTrees
readSubTrees subTrees (x:xs)
| "Subtree" `isPrefixOf` x =
let name = (words x) !! 1
treeDef = takeWhile (\x -> not ("Subtree" `isPrefixOf` x)) xs
rest = dropWhile (\x -> not ("Subtree" `isPrefixOf` x)) xs
(_, thisDT, _) = readDecisionTree' False subTrees treeDef
in readSubTrees ((name,thisDT):subTrees) xs
readLine :: String -> (Int,Bool,[String]) -- True = Value, False = Test
readLine s = (length (elemIndices '|' s), ')' `elem` s, vals)
where vals = words $
map (\x -> if x `elem` ":()/" then ' ' else x) $
dropWhile (`elem` "| ") s
simpleDT =
["localDefCountSum <= 4 : p (101.0/6.0)",
"localDefCountSum > 4 : u (7.0)"]
simpleDT2 = [
"isArgument0 = t: u (33.0/1.4)",
"isArgument0 = f:",
"| isArgument1 = f: u (9.0/1.3)",
"| isArgument1 = t:",
"| | isRecursive1 = t: s (945.0/39.8)",
"| | isRecursive1 = f: u (2.0/1.0)"]
{-
Test "isArgument0" "=" "t"
(Value "u" 33.0 1.4)
(Test "isArgument0" "=" "f"
(Test "isArgument1" "=" "f"
(Value "u" 9.0 1.3)
(Test "isArgument1" "=" "t"
(Test "isRecursive1" "=" "t"
(Value "s" 945.0 39.8)
(Value "u" 2.0 1.0))
(Value "" 0.0 0.0)))
(Value "" 0.0 0.0))
-}
simpleDT3 = [
"isArgument0 = t: u (33.0/1.4)",
"isArgument0 = f:",
"| isArgument1 = f :[S1]",
"| isArgument1 = t:",
"| | isRecursive1 = t: s (945.0/39.8)",
"| | isRecursive1 = f: u (2.0/1.0)",
"",
"Subtree [S1]",
"",
"localDefCount <= 15 : u (281.0/1.4)",
"localDefCount > 15 : s (139.0/11.8)"]