Haskell在一个do块中获取多个输入和输出

Haskell take multiple input and outputs in a do block

提问人:Big Man 提问时间:12/16/2022 最后编辑:Big Man 更新时间:12/16/2022 访问量:121

问:

我一直在尝试在同一个 do 块中将输入和输出列表到控制台上,然后通过递归重复此函数,但我是 haskell 中的 IO 新手,不知道如何让它工作。

此外,我没有在递归上放置中断语句,因为我可以在使用完它后通过在控制台中按 control-c 来破坏它。

我的代码:

move2 m coords char = when (can_move m coords char) (print_maze (place_player m (move coords char)))

game_loop m coords = print_maze (place_player m coords)
    do 
        (char:chars) <- getLine
        maze2 <- move2 m coords (read char)
        putStrLn maze2
        putStrLn game_loop m coords

do 块前面的一行用于输出列表,但在递归中不能重复。

错误信息:

Unexpected do block in function application:
        do (char : chars) <- getLine
           maze2 <- move2 m coords (read char)
           putStrLn maze2
           putStrLn game_loop m coords
    You could write it with parentheses
    Or perhaps you meant to enable BlockArguments?
    |
107 |     do
    |     ^^^^...

它说这是唯一的错误,但我确信 do 块中还有其他错误。所有其他单独的函数都可以自行正常工作。

我不知道我将如何解决这个问题,所以 IO 中的任何信息将不胜感激,谢谢。

编辑:

我现在让 do 块工作,我只是有一个类型错误。

move2 m coords char = when (can_move m coords char) (print_maze (place_player m (move coords char)))

game_loop m coords = do
    print_maze (place_player m coords)
    let loop = do 
        (char:chars) <- getLine
        maze2 <- move2 m coords (char)
        putStrLn maze2
        if char /= 'c'
        then game_loop m coords
        else return ()
    loop

错误信息:

Couldn't match type `()' with `[Char]'
      Expected type: String
        Actual type: ()
    * In the first argument of `putStrLn', namely `maze2'
      In a stmt of a 'do' block: putStrLn maze2
      In the expression:
        do (char : chars) <- getLine
           maze2 <- move2 m coords (char)
           putStrLn maze2
           if char /= 'c' then game_loop m coords else return ()
    |
111 |         putStrLn maze2
    |                  ^^^^^
Haskell 递归 IO

评论

0赞 chi 12/16/2022
看起来你返回而不是 ,这可以满足对字符串的需求。另外,你确定吗?你可能只想在那里。如果循环需要变量的新值,则需要转换为函数,如 。move2IO ()IO StringputStrLnthen game_loop ...looplooplet loop x y z = do .... ; .... then loop newX newY newZ
0赞 thisisrandy 12/18/2022
回复:您的编辑,它看起来像是类型,这意味着是(又名“单位”)。 是 ,所以 unit 不是有效的第一个参数(而是期望 a )。你可以说或等价物,但我不确定你为什么要这样做,因为它只会打印.也许你的意思是退回别的东西?move2IO ()maze2()putStrLnString -> IO ()putStrLnStringprint maze2putStrLn $ show maze2()move2
0赞 thisisrandy 12/18/2022
顺便说一句,通常最好使用显式类型对顶级函数进行注释。这有两个目的:让其他人(以及你未来的自己)清楚地知道函数执行了什么样的类型转换,并且还有助于在开发过程中确认你正在编写你认为你正在编写的函数。在这种情况下,如果您希望具有除 之外的返回类型,则显式注解将捕获错误并阻止该函数在真空中编译。相反,您在其他地方看到了错误,这不太明显。move2IO ()

答:

2赞 chi 12/16/2022 #1

你不能在这样的块前放一条线。如果您想在开始循环之前执行某些操作,请改为遵循以下方案:do

example :: IO ()
example = do
   putStrLn "this is the line before the loop, to be run once"
   let loop = do
          putStrLn "here we are inside the loop"
          if someCondition
          then loop      -- repeat the loop
          else return () -- stop the loop
   loop -- start the loop defined above

评论

0赞 Big Man 12/16/2022
谢谢,我将使用此布局对其进行测试,看看是否可以让它工作
0赞 Big Man 12/16/2022
我现在让 do 块工作,我只是有一个类型错误。print_maze (place_player m 坐标) let loop = do (char:chars) <- getLine maze2 <- move2 m 坐标 (char) putStrLn maze2 if char /= 'c' then game_loop m coords else return () 循环 无法匹配类型 [char]' 预期类型:字符串 实际类型:() 此错误位于 putStrLn maze2 行上()' with
0赞 chi 12/16/2022
@BigMan 编辑您的问题,并在末尾添加新代码。放在评论中是不可读的。
0赞 Big Man 12/16/2022
对不起,没有意识到格式是这样改变的,它在编辑中,谢谢