我正在玩Graphics.GD
,我想将图像读取到Color
值的矩阵中,有点像这样:
rectFromImage :: Image -> IO [[Color]]
rectFromImage img = do
size <- imageSize img
return [[getPixel (x,y) img | x <- [1 .. fst size]] | y <- [1 .. snd size]]
显然,这不起作用,因为getPixel
返回IO Color
,而不是Color
:
Couldn't match type `IO Color' with `Foreign.C.Types.CInt'
Expected type: Color
Actual type: IO Color
In the return type of a call of `getPixel'
In the expression: getPixel (x, y) img
In the expression: [getPixel (x, y) img | x <- [1 .. fst size]]
如何在getPixel
调用的返回中"摆脱IO"?
sequence
是您正在寻找的神奇函数。sequence
获取IO操作列表,并使其成为IO值列表。打字签名术语:
sequence :: Monad m => [m a] -> m [a]
或者,更具体地说,在您的情况下:
sequence :: [IO a] -> IO [a]
所以你可以做,例如:
do
putStrLn "Enter three lines of input:"
irritatedUser <- sequence [getLine, getLine, getLine]
putStrLn (irritatedUser !! 2)
并且用户写入的最后一行将被打印回。
无论如何,在你的情况下,这意味着你想做
rectFromImage img = do
size <- imageSize img
sequence [sequence [getPixel (x,y) img | x <- [1 .. fst size]] | y <- [1 .. snd size]]
我偷偷打了两个sequence
电话,从你的[[IO Color]]
转到[IO [Color]]
,然后转到IO [[Color]]
。
一般来说,你永远不会"摆脱"IO,你只是向上传播它。