Haskell使用多个monad类型来执行子句 [英] Haskell do clause with multiple monad types

查看:146
本文介绍了Haskell使用多个monad类型来执行子句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Haskell中使用了一个名为的图形库。在这个库中,主函数返回一个 UI monad对象。当我尝试将 IO 值解压到局部变量时,我感到非常头疼,我收到抱怨不同monad类型的错误。



这是我的问题的一个例子。这是一个稍微修改过的标准主函数版本,正如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:右))= splitAt randomPosition xs
fmap(a :)(shuffle(left ++ right))


$ b $请注意第五行:

  labelsAndValues<  -  shuffle [1..10] 

其中返回以下错误:

 无法将类型'IO'与'UI'匹配
期望类型:UI [Int]
实际类型:IO [Int]
在'do' block:labelsAndValues< - shuffle [1..10]

至于我的问题,我该如何使用标准箭头符号(< - )解开 IO 函数,并继续将这些变量设置为 IO()而不是 UI(),所以我可以轻松地将它们传递给其他函数。

目前,我发现的唯一解决方案是使用 liftIO ,但这会导致转换为 UI monad类型,而我真的想继续使用 IO 类型。

解决方案A do block是针对特定类型的monad,不能只改变中间的类型。



您既可以转换动作,也可以将它嵌套在 do 。大部分时间的转换将为你准备好。例如,您可以嵌套使用 io 的嵌套 do ,然后仅在交互点处对其进行转换。



在你的情况下,ThreePennyUI包提供了一个 liftIOLater 函数来处理这个函数。


liftIOLater :: IO() - > UI()



安排稍后运行的IO操作。

为了执行逆向转换,您可以使用 runUI


runUI :: Window - > UI a - > IO a



在特定浏览器窗口中执行UI操作。还运行所有计划的IO操作。



I'm using a graphic library in Haskell called Threepenny-GUI. In this library the main function returns a UI monad object. This causes me much headache as when I attempt to unpack IO values into local variables I receive errors complaining of different monad types.

Here's an example of my problem. This is a slightly modified version of the standard main function, as given by Threepenny-GUI's code example:

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

Please notice the fifth line:

labelsAndValues <- shuffle [1..10]

Which returns the following error:

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]

As to my question, how do I unpack the IO function using the standard arrow notation (<-), and keep on having these variables as IO () rather than UI (), so I can easily pass them on to other functions.

Currently, the only solution I found was to use liftIO, but this causes conversion to the UI monad type, while I actually want to keep on using the IO type.

解决方案

A do block is for a specific type of monad, you can't just change the type in the middle.

You can either transform the action or you can nest it inside the do. Most times transformations will be ready for you. You can, for instance have a nested do that works with io and then convert it only at the point of interaction.

In your case, a liftIOLater function is offered to handle this for you by the ThreePennyUI package.

liftIOLater :: IO () -> UI ()

Schedule an IO action to be run later.

In order to perform the converse conversion, you can use runUI:

runUI :: Window -> UI a -> IO a

Execute an UI action in a particular browser window. Also runs all scheduled IO action.

这篇关于Haskell使用多个monad类型来执行子句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆