1

I am trying to make a program that solves the tower of hanoi. I made it a bit complicated just for exercise:

hanoi :: [Int] -> String
hanoi n
    | n > 0     = hanoi' n "1" "2" "3"
                    where hanoi' n a b c
                            | n == 0    = "|"
                            | otherwise = let pre   = hanoi' (n-1) a c b
                                              posle = hanoi' (n-1) b c a
                                              in pre ++ a ++ " ~~> " ++ c ++ posle    
    | otherwise = "Number must be greater than 0!!!"

But i get:

hanoi.hs:7:97: parse error on input ‘=’

Can someone please explain to me what is going on? I see now that i don't understand an important part of the language.

someoneb100
  • 141
  • 1
  • 13
  • `in` needs to be on the same column as `let`. Also, which line is line 7? Please write the full error message. – AJF Dec 09 '17 at 11:34
  • This is the full error message. The above code is the entire program. line 7 is the one before the `in` statement. i tried indenting in, does not work – someoneb100 Dec 09 '17 at 11:37
  • Did you [mix tabs and spaces](https://stackoverflow.com/questions/35855170/why-shouldnt-i-mix-tabs-and-spaces)? – Zeta Dec 09 '17 at 11:39
  • I thought of that, so i replaced all tab with spaces. Did not work – someoneb100 Dec 09 '17 at 11:40
  • Your follow up question is completely unrelated to the former. – Zeta Dec 09 '17 at 11:51

1 Answers1

3

Your where has to come after all guards.

hanoi :: [Int] -> String
hanoi n
    | n > 0     = hanoi' n "1" "2" "3"
    | otherwise = "Number must be greater than 0!!!"
  where hanoi' n a b c
         | n == 0    = "|"
         | otherwise = let pre   = hanoi' (n-1) a c b
                           posle = hanoi' (n-1) b c a
                       in pre ++ a ++ " ~~> " ++ c ++ posle

This is stated in 4.4.3, although it's somewhat hidden if you're not used to BNF-like syntax:

decl    →   (funlhs | pat) rhs

funlhs  →   var apat { apat }
    |   pat varop pat
    |   ( funlhs ) apat { apat }

rhs     →   = exp [where decls]
    |   gdrhs [where decls] 

gdrhs   →   guards = exp [gdrhs]

guards  →   | guard1, …, guardn         (n ≥ 1)

guard   →   pat <- infixexp         (pattern guard)
    |   let decls       (local declaration)
    |   infixexp        (boolean guard) 

rhs is the important token. It's the only part that contains the optional where. A guard may only contain expressions and be followed by other guards.

Zeta
  • 103,620
  • 13
  • 194
  • 236