You are not logged in.
Hello there Arch members! Thanks for being the awesome community that you are.
On my spare time I've been trying work out my programming muscles... as they are very weak.
What I've got here is haskell code to open a file, read its contents, parse the contents into a type I've defined, and output as much debugging info as i could manage to stdout.
The issue that I cant seem to grapple with is how to bind the final list to a symbol in my main function (ie: forrest <- makeforrest $ objs) so I can use it later.
I'd like the list to have elements that are singleton 2-trees so I can build a heap from the list. The immediate problem I run into is a type problem. If i were to add the code:
forest <- makeforrest objs
the compiler complains with "Couldn't match expected type 'IO t0' with actual type '[BinTree a0]'
Do I have to "unwrap" objs of the IO monad somehow first?
Any advice/help/insight is greatly appreciated.
module Main where
import Text.ParserCombinators.Parsec
import System.Environment
import System.IO
import Control.Monad
import CustTree
data DummyBag = DummyBag {key::String, val::Integer}
deriving (Show,Read,Eq)
parseDataFile :: GenParser Char st [DummyBag]
parseDataFile =
do obs <- many keyAndVal
eof
return obs
keyAndVal = do key <- many1 letter
spaces
val <- anyChar `manyTill` newline
return (DummyBag key (read val))
--extract :: DummyBag a -> (Integer,String)
extract (DummyBag key val) = (val,key)
singleton :: (Show a) => a -> BinTree a
singleton f = NodeBT f Empty Empty
makeforrest :: (Show a) => [a] -> [BinTree a]
makeforrest [] = []
makeforrest xs = map singleton xs
main :: IO ()
main = do args@(f:opts) <- getArgs
handle <- openFile f ReadMode
contents <- hGetContents handle
putStrLn ("DEBUG: got input\n" ++ contents)
let objs = case parse parseDataFile "(unknown)" contents of
Left err -> error $ "Input:\n " ++ show contents ++
"\nError:\n" ++ show err
Right results -> results
putStrLn "Debug: parsed: ";print objs
putStrLn "Debug: converted to forest:";print ( makeforrest objs )
return ()
And here is the output when tested on very simple input data:
DEBUG: got input
ABC 1
DEF 2
GHI 3
JKL 4
MNO 5
PQR 6
STU 7
VWY 8
YZ 9
Debug: parsed:
[DummyBag {key = "ABC", val = 1},DummyBag {key = "DEF", val = 2},DummyBag {key = "GHI", val = 3},DummyBag {key = "JKL", val = 4},DummyBag {key = "MNO", val = 5},DummyBag {key = "PQR", val = 6},DummyBag {key = "STU", val = 7},DummyBag {key = "VWY", val = 8},DummyBag {key = "YZ", val = 9}]
Debug: converted to forest:
[NodeBT (DummyBag {key = "ABC", val = 1}) Empty Empty,NodeBT (DummyBag {key = "DEF", val = 2}) Empty Empty,NodeBT (DummyBag {key = "GHI", val = 3}) Empty Empty,NodeBT (DummyBag {key = "JKL", val = 4}) Empty Empty,NodeBT (DummyBag {key = "MNO", val = 5}) Empty Empty,NodeBT (DummyBag {key = "PQR", val = 6}) Empty Empty,NodeBT (DummyBag {key = "STU", val = 7}) Empty Empty,NodeBT (DummyBag {key = "VWY", val = 8}) Empty Empty,NodeBT (DummyBag {key = "YZ", val = 9}) Empty Empty]
Offline
import CustTree
is that a private import? if it is upload it
Miscusi for my bad english
Offline
module CustTree where
data Tree a = Node a [Tree a] deriving Show
data BinTree a = Empty | NodeBT a (BinTree a) (BinTree a)
deriving Show
data BinTree' a = Leaf a | NodeBT' a (BinTree' a) (BinTree' a)
deriving Show
-- Operations can be grouped into 'single' operations and 'global'
-- operations. Insertions and deletions are considered to belong
-- to the 'single' group where the following belong to latter.
depth :: Tree a -> Int
depth (Node _ []) = 1
depth (Node _ ts) = 1 + maximum (map depth ts)
depth' :: BinTree a -> Int
depth' Empty = 0
depth' (NodeBT _ lt rt) = 1 + max (depth' lt) (depth' rt)
--Count empty leaves in a tree.
countEmpty :: BinTree a -> Int
countEmpty Empty = 1
countEmpty (NodeBT _ lt rt) = countEmpty lt + countEmpty rt
--Suppose the nodes contain integers, summing the values
tsum :: BinTree Int -> Int
tsum Empty = 0
tsum (NodeBT a lt rt) = a + (tsum lt) + (tsum rt)
tsum' :: BinTree' Int -> Int
tsum' (Leaf a) = a
tsum' (NodeBT' a lt rt) = a + (tsum' lt) + (tsum' rt)
preorder :: BinTree a -> [a]
preorder Empty = []
preorder (NodeBT a lt rt) = [a] ++ preorder lt ++ preorder rt
inorder :: BinTree a -> [a]
inorder Empty = []
inorder (NodeBT a lt rt) = inorder lt ++ [a] ++ inorder rt
postorder :: BinTree a -> [a]
postorder Empty = []
postorder (NodeBT a lt rt) = postorder lt ++ postorder rt ++ [a]
Thanks for taking a look
Last edited by ickabob (2011-03-23 06:58:47)
Offline
forest <- makeforrest objs
the compiler complains with "Couldn't match expected type 'IO t0' with actual type '[BinTree a0]'
Do I have to "unwrap" objs of the IO monad somehow first?
Any advice/help/insight is greatly appreciated.makeforrest :: (Show a) => [a] -> [BinTree a] makeforrest [] = [] makeforrest xs = map singleton xs main :: IO () main = do args@(f:opts) <- getArgs handle <- openFile f ReadMode contents <- hGetContents handle putStrLn ("DEBUG: got input\n" ++ contents) let objs = case parse parseDataFile "(unknown)" contents of Left err -> error $ "Input:\n " ++ show contents ++ "\nError:\n" ++ show err Right results -> results putStrLn "Debug: parsed: ";print objs putStrLn "Debug: converted to forest:";print ( makeforrest objs ) return ()
While looking at your code it seems like makeforrest is pure.
Adding:
forest <- makeforrest objs will ad a monadic computation of type IO t0. All though list are monads in haskell it's not the same monad. What you want to do is either:
let forest = makeforrest objs , or
forest <- return $ makeforrest objs
The later one is a bit of a hack that takes value, place it in IO and takes it out.
Happy hacking.
Offline