简体   繁体   English

如何在 Haskell 中做一个递归主 function

[英]How to do a recursive main function in Haskell

So I wanted to make a program that prints out a ASCII triangle.所以我想制作一个打印出 ASCII 三角形的程序。 The program asks you the height that you want your triangle to be and prints it out and does it until the number you put in is 7 , then it draws the traingle of height 7 and the program stops.该程序会询问您希望三角形的高度并将其打印出来并一直执行,直到您输入的数字为7 ,然后它绘制高度为 7 的三角形,程序停止。 The trinagle that is print out is made out of '*' if the number is even and '#' if the number is odd.如果数字是偶数,打印输出的三角形由“*”组成,如果数字是奇数,则由“#”组成。 I wanted to do that by recursively calling the main function我想通过递归调用function 来做到这一点

triangle level character = draw level character 1 
      where draw level character accumulator
             | level <=0 = putStr("")
             | level > 0 = do 
                 putStrLn (replicate level ' ' ++ replicate accumulator character)
                 draw (level-1) character (accumulator+2)

main = do
    number <- readLn :: IO Int
    if(number `mod` 2 == 0)
      then
        triangle number'*'
        main 
     else if (number == 7)
       then triangle number '#'
       else triangle number '#'
       main

The error i get is我得到的错误是

• Couldn't match expected type ‘IO () -> IO ()’
              with actual type ‘IO ()’
• The function ‘triangle’ is applied to three arguments,
  but its type ‘Int -> Char -> IO ()’ has only two
  In the expression: triangle number '*' main
  In a stmt of a 'do' block:
    if (number `mod` 2 == 0) then
        triangle number '*' main
    else
        if (number == 7) then
            triangle number '#'
        else
            triangle number '#' main

The error says:错误说:

• The function ‘triangle’ is applied to three arguments,
  but its type ‘Int -> Char -> IO ()’ has only two
  In the expression: triangle number '*' main

So the compiler has parsed your code as triangle number '*' main ;因此编译器已将您的代码解析为triangle number '*' main this means that the line break between triangle number '*' and main is not being interpreted as a do block statement break, and the reason is that you're not inside a do block!这意味着triangle number '*'main之间的换行符不会被解释为do块语句中断,原因是您不在do块内! The same error follows in the later else clause for triangle number '#' main .triangle number '#' main的后面else子句中也出现了同样的错误。 The fix is to add a do :解决方法是添加一个do

main = do
    number <- readLn :: IO Int
    if(number `mod` 2 == 0)
      then do
        triangle number'*'
        main 
     else if (number == 7)
       then triangle number '#'
       else do
         triangle number '#'
         main

If you have trouble with Haskell's layout rules, you can always use explicit curly braces {} around blocks and semicolons ;如果你对 Haskell 的布局规则有疑问,你总是可以在块和分号周围使用显式的花括号{ ... } ; between block items, to check your understanding of how your code is being parsed.块项目之间,以检查您对如何解析代码的理解。

main :: IO ();  -- end signature
main = do {  -- begin ‘do’
    number <- readLn :: IO Int;  -- end statement
    if (number `mod` 2 == 0)
      then do {
        triangle number '*';
        main;
      }
      else if (number == 7)
      then triangle number '#'
      else do {
        triangle number '#';
        main;
      };  -- end ‘do’, end statement (starting with ‘if…’)
};  -- end ‘do’, end equation

Aside, note that I put spaces around the character literal like … number '*' … instead of … number'*' … .另外,请注意我在字符文字周围放置了空格,例如… number '*' …而不是… number'*' … Apostrophes are allowed in identifiers (as an ASCII approximation of the “prime” symbol ), so if you changed this to number'X' then that would be parsed as a single name, number'X' , rather than a name number followed by a character literal 'X' , which may be confusing.标识符中允许使用撇号(作为“主要”符号'的 ASCII 近似值),因此如果您将其更改为number'X' ,那么它将被解析为单个名称number'X' ,而不是后面的名称number通过字符文字'X' ,这可能会令人困惑。

First, you're missing a do here:首先,你在这里错过了一个do

      then
        triangle number'*'
        main 

The two lines after then are being interpreted together as triangle number '*' main (which is how it's quoted in the error message if you notice). then的两行将被一起解释为triangle number '*' main (如果您注意到,这就是它在错误消息中的引用方式)。 In order to have the two lines interpreted separately as subsequent actions, they need to be inside a do :为了将这两行分别解释为后续操作,它们需要在do内:

      then do
        triangle number'*'
        main 

And the same problem, plus ambiguous indentation, exists with the very last block.最后一个块存在同样的问题,加上不明确的缩进。 It should probably be:应该是:

else do
  triangle number '#'
  main

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM