Reputation: 4356
I have following toy haskell code for binary search tree. The function preorderV is to traverse the tree with a function applying to every element. It works fine for normal function. However if I apply function "print", I got compiling error. How could I make function related to IO work with preorderV?
Thanks
Code:
data BSTree a = EmptyTree | Node a (BSTree a) (BSTree a) deriving (Show)
data Mode = IN | POST | PRE
singleNode :: a -> BSTree a
singleNode x = Node x EmptyTree EmptyTree
bstInsert :: (Ord a) => a -> BSTree a -> BSTree a
bstInsert x EmptyTree = singleNode x
bstInsert x (Node a left right)
| x == a = Node a left right
| x < a = Node a (bstInsert x left) right
| x > a = Node a left (bstInsert x right)
buildTree :: String -> BSTree String
buildTree = foldr bstInsert EmptyTree . words
preorderV :: (a->b) -> BSTree a -> BSTree b
preorderV f EmptyTree = EmptyTree
preorderV f (Node x left right) = Node (f x) (preorderV f left) (preorderV f right)
Error:
Couldn't match type ‘BSTree’ with ‘IO’
Expected type: IO (IO ())
Actual type: BSTree (IO ())
In a stmt of a 'do' block: preorderV print $ buildTree content
Upvotes: 0
Views: 337
Reputation: 52290
your code works so far but you got a BSTree (IO ())
back and as you use this inside a do
Block (main
most likely) you get the error.
what you now can do is fold over the tree to get the actions back, then you can use sequence
or something similar to use each of those actions one after the other:
foldT :: (a -> s -> s) -> s -> BSTree a -> s
foldT _ s EmptyTree = s
foldT f s (Node a left right) =
let s' = foldT f s left
s'' = f a s'
in foldT f s'' right
main :: IO ()
main = do
let doPrint = preorderV print $ buildTree "C A B D E"
folded = foldT (:) [] doPrint
sequence_ . reverse $ folded
This will print
λ> :main
"A"
"B"
"C"
"D"
"E"
BTW: Your preorderV
is usually called map
;)
Upvotes: 1
Reputation: 52057
The type of preorderV print $ buildTree content
is BSTree (IO ())
, that is, you are creating a binary tree of IO computations - you don't have an IO computation itself.
To do what I think you want to do you need to create a monadic version of preorderV
which has the following type:
preorderVM :: (a -> IO ()) -> BSTree a -> IO ()
preorderVM f EmptyTree = ... -- what do you want to do here?
preorderVM f (Node x left right) = do
f x
preorderVM f left
preorderVM f right
Upvotes: 3