Смешивание монад в Haskell
Я пытаюсь работать с 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";
.... }
Я могу видеть, как тип op подразумевается как нечто отличное от возвращаемого типа putStrLn, но я не уверен, как я буду реинжинирировать этот код для правильной компиляции. Могу ли я просто изменить возвращаемый тип функции op?
Спасибо
Ответы
Ответ 1
Ваш вызов putStrLn
, записанный в op
, находится в монаде IO
. Вам нужно будет поднять его в монаду Ubigraph
, используя
liftIO $ putStrLn "foo"
Такие функции подъема помогут вам получить доступ к монодичным функциям ниже в стеке. В этом случае Ubigraph
является монадой-читателем, состоящей из монады IO, а монада IO находится внизу. Поэтому вещи в IO должны быть сняты.
liftIO
относится к классу MonadIO
, в пакете трансформаторов.