Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何在一个函数中执行多个语句?_Haskell_Recursion_Functional Programming - Fatal编程技术网

Haskell 如何在一个函数中执行多个语句?

Haskell 如何在一个函数中执行多个语句?,haskell,recursion,functional-programming,Haskell,Recursion,Functional Programming,我正在学习Haskell,为了完成一项任务,我必须打印一个蛇和梯子游戏。开始时,我正在尝试打印电路板,这就是我所做的 import Data.List aRow :: Int -> String aRow n = "+" ++ take (4*n) (intercalate "" (repeat "---+")) ++ "\n|" ++ take (4*n) (intercalate "" (repeat " |")) ++ "\n" board :: Int ->

我正在学习Haskell,为了完成一项任务,我必须打印一个蛇和梯子游戏。开始时,我正在尝试打印电路板,这就是我所做的

import Data.List
aRow :: Int -> String
aRow n = "+" ++ take (4*n) (intercalate "" (repeat "---+")) ++ "\n|" ++      take (4*n) (intercalate "" (repeat "   |")) ++ "\n"

board :: Int -> Int -> IO()
board 1 y = putStrLn (aRow y)
我想要另一个board实例,这样它就可以接受参数x和y

board x y = putStrLn (aRow y)
            board (x-1) y
我知道我不能像这样调用多个语句,但是有人能提供一些关于我如何处理这些语句的见解吗?我想用参数“y”来调用aRow,然后做“x”次

谢谢

另外:当我调用board 1 y时,我将其作为输出: 董事会1 5 +--+--+--+--+--+
| | | | | |

我认为最干净的方法是在不进行任何IO的情况下创建电路板,然后在最后只使用IO打印出来

您可以使用concat和replicate来实现这一点:

board :: Int -> Int -> String
board x y = concat (replicate y (aRow x))
你可能在底部漏了一行,但我会让你弄清楚的

顺便说一句,取4*n interlate repeat-+与concat replicate n-+相同,因此您可以将aRow写为:

编辑:我将使用unlines::[String]->String来连接多行上的多个字符串:

aRow :: Int -> String
aRow n = unlines
  [ '+' : concat (replicate n "---+")
  , '|' : concat (replicate n "   |")
  ]

我认为最干净的方法是在不进行任何IO的情况下创建电路板,然后在最后只使用IO打印出来

您可以使用concat和replicate来实现这一点:

board :: Int -> Int -> String
board x y = concat (replicate y (aRow x))
你可能在底部漏了一行,但我会让你弄清楚的

顺便说一句,取4*n interlate repeat-+与concat replicate n-+相同,因此您可以将aRow写为:

编辑:我将使用unlines::[String]->String来连接多行上的多个字符串:

aRow :: Int -> String
aRow n = unlines
  [ '+' : concat (replicate n "---+")
  , '|' : concat (replicate n "   |")
  ]
因此,您需要执行一个IO,然后执行另一个IO操作。它们一起也应该是一个IO。因此,您正在寻找一个具有签名IO->IO->IO的组合器。你可以。。。哦,天哪,这会产生很多不相关的结果。而且

您的IO->IO->IO是此签名的特例,通过设置m~IO和a~b~获得。所以,你可以写

board x y = putStrLn (aRow y)
         >> board (x-1) y
因为这些一元排序运算符在Haskell中经常使用,所以它具有特殊的语法糖语法,即

board x y = do
    putStrLn (aRow y)
    board (x-1) y
好的,这是可行的,但它不是真正的惯用语。带有“计数器变量”x的手动递归“循环”很麻烦,而且很容易出错。您需要正确地获得初始、终止和步进条件。实际上,你所做的就是连续x次执行同一个动作。所以你真的对Int->IO->IO感兴趣。再一次这一次来得稍微早一点

replicateM_ :: Applicative m => Int -> m a -> m ()
所以

更妙的是,正如回力棒所言,完全避免IO循环。

因此您希望执行一个IO,然后执行另一个IO操作。它们一起也应该是一个IO。因此,您正在寻找一个具有签名IO->IO->IO的组合器。你可以。。。哦,天哪,这会产生很多不相关的结果。而且

您的IO->IO->IO是此签名的特例,通过设置m~IO和a~b~获得。所以,你可以写

board x y = putStrLn (aRow y)
         >> board (x-1) y
因为这些一元排序运算符在Haskell中经常使用,所以它具有特殊的语法糖语法,即

board x y = do
    putStrLn (aRow y)
    board (x-1) y
好的,这是可行的,但它不是真正的惯用语。带有“计数器变量”x的手动递归“循环”很麻烦,而且很容易出错。您需要正确地获得初始、终止和步进条件。实际上,你所做的就是连续x次执行同一个动作。所以你真的对Int->IO->IO感兴趣。再一次这一次来得稍微早一点

replicateM_ :: Applicative m => Int -> m a -> m ()
所以


更妙的是,正如回力棒所言,完全避免IO循环。

您只需对两个单元函数进行排序:

board x y = putStrLn (aRow y) >> board (x - 1) y
或使用do符号

请注意,x==0表示更自然的基本情况:

board 0 y = return ()
board x y = do
   putStrLn (aRow y)
   board (x - 1) (aRow y)

请参阅Boomerang的答案,了解编写函数的更惯用方法。

您只需对两个一元函数进行排序:

board x y = putStrLn (aRow y) >> board (x - 1) y
或使用do符号

请注意,x==0表示更自然的基本情况:

board 0 y = return ()
board x y = do
   putStrLn (aRow y)
   board (x - 1) (aRow y)

请参阅Boomerang的答案,了解编写函数的更为惯用的方法。

我会找到你,我会拥抱你“排队Liam Neeson voice”。我会找到你,我会拥抱你“排队Liam Neeson voice”。