
On Tuesday 06 July 2010 11:15:12, Tom Hobbs wrote:
Sorry, I meant to send this to the list, rather than just to Stephen (sorry for the Spam).
Tom
---------- Forwarded message ---------- From: Tom Hobbs
Date: Tue, Jul 6, 2010 at 10:12 AM Subject: Re: [Haskell-beginners] More Deserialization Woes To: Stephen Tetley Hello again,
I've been reading through various tutorials and they all put IO as the outermost monad, like you suggest. However, I don't think that's what I want.
My IO operation is reading from a network stream, not a file, so I want a failure halfway through should signify a complete failure. So, I believe that the type signature for my function should be;
ping :: String -> PortNumber -> Maybe (IO [String])
because the result "Just []" is a valid one and does not signify a failure.
Nevertheless, IO (Maybe [String]) is, I believe, the appropriate type.
However, the result of "IO [Just "a", Just "b", Nothing, Nothing]" would signify that communication failed halfway through and would not make sense in my context. This is what the advice seems to be suggesting I write. But in this case, I'd prefer to return "Nothing" to signify that a problem occurred.
You can do that by applying sequence (at the type [Maybe String] -> Maybe [String]). Say you have ping0 :: args -> IO [Maybe String] then you'd use ping :: args -> IO (Maybe [String]) ping = fmap sequence ping0
So my first question is; because I want to do something so different from the majority of the articles I've read; am I in a niche where my requirement makes sense, or does my requirement make no sense - a theory that is backed up by the fact that no one else seems to be doing that...
Now, I'm not sure I can get there by myself, since I'm struggling to get the right incantation of catching errors but I'll keep plugging away at that for a while.
But can someone help me with my next question also.
Is it possible, to extract the values out of the IO monad so it can be used in pure functions.
Yes, but you needn't (and shouldn't in general). The general pattern is main = do someValues <- getDataIOAction let otherValues = pureStuff someValues outputIO otherValues
For example, once ping has returned it's Maybe [IO String], I would like to be able to create another function such as;
purePing :: String -> PortNumber -> Maybe [String] purePing a p = removeIOMonad (ping a p) where removeIOMonad Nothing = Nothing removeIOMonad [] = Just [] removeIOMonad (x:xs) = clevelDropIOMagic x : removeIOMonad xs
...or something...
Once the IO [String] has been read from the stream, no further IO is necessary, so any other function should be able to just use the list and not worry about the IO stuff.
Again my questions are, Is this an okay thing to do, or is my design/idea very, very wrong?
Thanks again for the help,
Tom