You are not logged in.

#1 2011-03-13 01:00:11

ickabob
Member
Registered: 2010-06-21
Posts: 9

Got a question for you haskellers

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

#2 2011-03-23 03:45:45

slacknatcher
Member
From: Chile
Registered: 2009-07-08
Posts: 55

Re: Got a question for you haskellers

 
import CustTree

is that a private import? if it is upload it


Miscusi for my bad english

Offline

#3 2011-03-23 06:39:05

ickabob
Member
Registered: 2010-06-21
Posts: 9

Re: Got a question for you haskellers

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 smile

Last edited by ickabob (2011-03-23 06:58:47)

Offline

#4 2011-03-23 14:08:09

dagle
Member
Registered: 2009-01-04
Posts: 13

Re: Got a question for you haskellers

ickabob wrote:

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. smile

Offline

Board footer

Powered by FluxBB