So I wanted to make a program that prints out a ASCII triangle. 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. 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
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; 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! The same error follows in the later else clause for triangle number '#' main. The fix is to add a 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 ; 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'*' …. 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.
First, you're missing a do here:
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). In order to have the two lines interpreted separately as subsequent actions, they need to be inside a 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With