Haskell使用多个monad类型来执行子句 [英] Haskell do clause with multiple monad types
问题描述
我在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
类型。
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屋!