Haskell IO (Monads?)

Programming, for all ages and all languages.
Post Reply
User avatar
Alboin
Member
Member
Posts: 1466
Joined: Thu Jan 04, 2007 3:29 pm
Location: Noricum and Pannonia

Haskell IO (Monads?)

Post by Alboin »

Hello,

I've been working on my Haskell recently, and I've come to an issue. I'm working on an interpreter for a small stack based language I made. However, I can not see how one is to use IO inside the body of a function.

For example, I have a function:

Code: Select all

{- 'Just a structure that keeps a rough 'type' of a token and the actual token. Used for parsing and the stack. -}
data Token = Tn { tok_type, tok_data :: String }

{- The first arg is the command and the second is the stack. We return the modified stack. -}
eval_command :: String -> [Token] -> [Token]
eval_command "dup" (x:xs) = ([x] ++ [x] ++ xs)
Now, I have a 'print' command.

Code: Select all

eval_command "print" (x:xs) = do
        putStrLn x
        return xs
However, due to the IO, it returns (or should, if Google has proven to be true.) '[Token] IO'. My problem is that the rest of my code expects just [Token].

Does anyone know how this is performed in Haskell? I don't feel that using [Token] IO everywhere would be a good idea, yet other Haskell code I've looked at does seem to do this.

I'm not 100% on monads yet, however, this seems to be a problem of a more 'coding paradigm' sort, so I don't think that should be a problem.

Thanks for any 'pure' enlightenment,
Alboin
C8H10N4O2 | #446691 | Trust the nodes.
NReed
Posts: 24
Joined: Wed May 28, 2008 10:56 pm

Post by NReed »

hehe, I have been in the exact situation as you very recently so you gave me the inspiration to stop hovering and finally register.


Here is example code of what you should do:

Code: Select all

print1 (x:xs) = do
        putStrLn x
        return xs

a <- print1 ["a1","b2","c3"]
I can't really explain the intricacies since I barely understand them. But basically "<-" will take it out of IO.

I hope this helped.
TverrBjelke
Posts: 23
Joined: Thu Apr 24, 2008 6:14 am

Haskell IO (Monads?)

Post by TverrBjelke »

Hu! I am really fond of hearing someone else is capable of doing some Haskell! Wondering, how it come you using Haskell for your project?

Still my last active work with Haskell is somewhat "ago".
But I remember this "monads" are whole subject of its own, opening new doors, good to know when you have to deal with real live and performance issues.

I remember this to be a helpful introducing document:
http://www.haskell.org/tutorial/monads.html
But you probably already know it...

Alot of deep-diving texts were published about "monads" and about I/O.

all Thumbs,
Tverr
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

Haskell is a pure functional language. That means that all code does not produce unregistered side effects.

I/O however, does have side effects: it presents the user with an option. It therefore returns different values everytime you run it, which is unacceptable in normal functions. Hence I/O can not be freely mixed with normal haskell code.

Instead Haskell uses the IO Monad. This makes the user input and output reappear as a constant, by attaching the entire I/O state to it. Hence you get IO String, IO Int, meaning String + IO status, Int + IO Status

To keep everything safe, you can not alter variables that have been bound to IO to unbound ones, as that would mean they are suddenly constant over all possible forms of I/O. Instead, you have to bind unbound variables to I/O

Code: Select all

main = do x <- readFile "filename"
          return (process x)
do tells you this is a series of I/O bound commands in order.
readFile is an I/O bound function, returning the contents of a file.
x gets locally bound to an IO String via the <- operator. That means for the remainder of the function, it remains constant. From here on, x can be used as if it were no longer bound by IO.
process x will then do the requested operations on the unbound variable x,
the result will then be wrapped up in return, because as it leaves the function, the result will once again have to be bound to IO.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Alboin
Member
Member
Posts: 1466
Joined: Thu Jan 04, 2007 3:29 pm
Location: Noricum and Pannonia

Post by Alboin »

Wondering, how it come you using Haskell for your project?
Educational purposes. It's more of a toy project.

Thanks all for the help. I'll definitely be looking into monads. With just a bit of reading from yesterday, I see the err of my post. I hadn't thought about how the environment was transferred about and such.

Thanks again,
Alboin
C8H10N4O2 | #446691 | Trust the nodes.
Post Reply