Смешивание монад в Хаскеле - PullRequest
10 голосов
/ 27 апреля 2011

Я пытаюсь работать с Ubigraph в haskell, но я считаю, что моя проблема более общая. Я пытаюсь скомпилировать:

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 ()

и я получаю

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";
       .... }

Я вижу, что тип операции подразумевается как нечто отличное от возвращаемого типа putStrLn, но я не уверен, как бы я реинжинировал этот код для правильной компиляции. Могу ли я просто изменить тип возврата функции op?

Спасибо

1 Ответ

12 голосов
/ 27 апреля 2011

Ваш вызов putStrLn похоронен в op в монаде IO.Вам нужно будет поднять его в монаду Ubigraph, используя

 liftIO $ putStrLn "foo"

. Такие функции подъема помогут вам получить доступ к монадическим функциям ниже в стеке.В этом случае Ubigraph - это монада Reader, составленная из монады IO, а монада IO находится внизу.Поэтому вещи в IO должны быть отменены.

liftIO относится к классу MonadIO, в пакете трансформаторов .

...