【发布时间】:2015-06-22 13:20:18
【问题描述】:
我在 Haskell 中使用了一个名为 Threepenny-GUI 的图形库。在这个库中,主函数返回一个UI monad 对象。这让我很头疼,因为当我尝试将 IO 值解压缩到局部变量中时,我收到了抱怨不同 monad 类型的错误。
这是我的问题的一个例子。这是标准 main 函数的略微修改版本,由 Threepenny-GUI 的代码示例给出:
main :: IO ()
main = startGUI defaultConfig setup
setup :: Window -> UI ()
setup w = do
labelsAndValues <- shuffle [1..10]
shuffle :: [Int] -> IO [Int]
shuffle [] = return []
shuffle xs = do randomPosition <- getStdRandom (randomR (0, length xs - 1))
let (left, (a:right)) = splitAt randomPosition xs
fmap (a:) (shuffle (left ++ right))
请注意第五行:
labelsAndValues <- shuffle [1..10]
返回以下错误:
Couldn't match type ‘IO’ with ‘UI’
Expected type: UI [Int]
Actual type: IO [Int]
In a stmt of a 'do' block: labelsAndValues <- shuffle [1 .. 10]
关于我的问题,我如何使用标准箭头符号 (<-) 解压缩 IO 函数,并继续将这些变量作为 IO () 而不是 UI (),这样我就可以轻松地传递它们到其他功能。
目前,我找到的唯一解决方案是使用liftIO,但这会导致转换为UI monad 类型,而我实际上想继续使用IO 类型。
【问题讨论】:
-
你不能在 do 块中途改变 monad
-
你想继续使用IO类型是什么意思?
liftIO $ do ... a block of IO code ...会是你要找的吗? -
根据这个线程的结论,我提出了一个关于如何集成打印的新问题。任何帮助将不胜感激 - stackoverflow.com/questions/30988595/…
-
@vondip 你能说一下你是如何使用 liftIO 转换为 UI monad 的吗?我也有类似的问题:stackoverflow.com/questions/51906879/…
标签: haskell monads threepenny-gui