Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing Monads in Haskell

I'm trying to work with Ubigraph in haskell, but I believe my problem is more generic. I'm trying to compile:

import Graphics.Ubigraph
import Control.Monad
import System.Posix.Unistd

main = do
    h <- initHubigraph "http://127.0.0.1:20738/RPC2"
    runHubigraph op h

op = do
  clear
  vs <- mapM (const newVertex) [0..200]
  mapM_ (setVAttr (VShape Sphere)) vs
  putStrLn "something"
  let bind i = zipWithM (\a b -> newEdge (a,b)) vs (drop i vs ++ take i vs)
  mapM_ bind [1..15]
  mapM_ (removeVertex) vs
  return ()

and I am getting

Couldn't match expected type `Control.Monad.Trans.Reader.ReaderT
                                Ubigraph IO a0'
            with actual type `IO ()'
In the return type of a call of `putStrLn'
In a stmt of a 'do' expression: putStrLn "something"
In the expression:
  do { clear;
       vs <- mapM (const newVertex) [0 .. 200];
       mapM_ (setVAttr (VShape Sphere)) vs;
       putStrLn "something";
       .... }

I can see how the type of op is being implied as something different from the return type of putStrLn, but I am not sure how I would reengineer this code to compile properly. Can I simply change the return type of the op function?

Thanks

like image 591
Charles Durham Avatar asked Apr 27 '11 15:04

Charles Durham


1 Answers

Your call to putStrLn buried down in op is in the IO monad. You will need to lift it into the Ubigraph monad, using

 liftIO $ putStrLn "foo"

Such lifting functions help you access monadic functions lower in the stack. In this case, Ubigraph is a Reader monad composed with the IO monad, and the IO monad is at the bottom. So things in IO must be lifted.

liftIO is from the MonadIO class, in the transformers package.

like image 111
Don Stewart Avatar answered Sep 20 '22 13:09

Don Stewart