[Haskell-cafe] tips on using monads
Neil Brown
nccb2 at kent.ac.uk
Mon May 18 06:08:41 EDT 2009
Michael P Mossey wrote:
> I've got one of those algorithms which "threatens to march off the
> right edge" (in the words of Goerzen et al). I need something like a
> State or Maybe monad, but this is inside the IO monad. So I presume I
> need StateT or MaybeT. However, I'm still (slowly) learning about
> monads from first principles. I thought I might present my code and
> get some pointers... maybe someone could actually show me how to
> rewrite it, which would be a neat way to see MaybeT and StateT in
> action. I'm hoping to get anything from a one-line response to a
> rewrite of my code. Anything will help.
Here's a version using ErrorT from mtl. I added some missing IO bits on
your types; the type error that remains is for you to fix :-) With
ErrorT you can use throwError when you want to break out of the block
and give back an error, which seems to fit what you were doing. The
downside is you have to add all these liftIO bits wherever you do a
plain IO computation.
insertNote :: NoteRecord -> Connection -> IO ()
insertNote nr conn = either putStrLn return =<< runErrorT
(do -- Check if it exists in the database already.
status <- liftIO $ checkPreExistingText nr conn
when status $ throwError "Skipping... text exists already."
-- Find best fit for all topics and source.
-- See type signatures below.
bestFitTopics <- liftIO $ fitTopics nr conn
bestFitSource <- liftIO $ fitSource nr conn
case any isNothing bestFitTopics of
True -> throwError "Error... some topic couldn't be matched."
False ->
case bestFitSource of
Nothing -> throwError "Error.. source couldn't be matched."
_ -> do b <- liftIO $ isUserOkay nr bestFitTopics bestFitSource
when (not b) $ throwError "Abort due to user request."
-- Create a new NoteRecord with matched
-- and validated topics/source.
let nrValidated =
nr { recordTopics = bestFitTopics
, recordSource = bestFitSource }
liftIO $ insertRow nrValidated conn
)
checkPreExistingText :: NoteRecord -> Connection -> IO Bool
fitTopics :: NoteRecord -> Connection -> IO [Maybe String]
fitSource :: NoteRecord -> Connection -> IO (Maybe String)
isUserOkay :: NoteRecord -> [Maybe String] -> Maybe String -> IO Bool
insertRow :: NoteRecord -> Connection -> IO ()
Thanks,
Neil.
More information about the Haskell-Cafe
mailing list