Home > Software engineering >  Syntax error in expression (unexpected `;', possibly due to bad layout) in line 50
Syntax error in expression (unexpected `;', possibly due to bad layout) in line 50

Time:06-17

Hello I'm writing this code as a beginner Haskell project that solves a very basic version of minesweeper. Details are unimportant but I keep getting a syntax error on line 50 in the isGoal function Syntax error in expression (unexpected `;', possibly due to bad layout). This function is supposed to test if the al list is an empty list and return true if so but I keep getting this syntax error. I'm a beginner so any help is appreciated

type Cell = (Int,Int)
data MyState = Null | S Cell [Cell] String MyState deriving Show

up :: MyState -> MyState
up (S (0, _) [_] _ _)= Null
up (S (0, _) (_:_) _ _)= Null
up (S (x,y) [c] "" s)= S ((x-1),y) [c] "up" (S (x,y) [c] "" s)
up (S (x,y) [c] b s)= S ((x-1),y) [c] "up" (S (x,y) [c] b s)
up (S (x,y) (c:cs) "" s)= S ((x-1),y) (c:cs) "up" (S (x,y) (c:cs) "" s)
up (S (x,y) (c:cs) b s)= S ((x-1),y) (c:cs) "up" (S (x,y) (c:cs) b s)

down :: MyState -> MyState
down (S (3, _) [_] _ _)= Null
down (S (3, _) (_:_) _ _)= Null
down (S (x,y) [c] "" s)= S ((x 1),y) [c] "down" (S (x,y) [c] "" s)
down (S (x,y) [c] b s)= S ((x 1),y) [c] "down" (S (x,y) [c] b s)
down (S (x,y) (c:cs) "" s)= S ((x 1),y) (c:cs) "down" (S (x,y) (c:cs) "" s)
down (S (x,y) (c:cs) b s)= S ((x 1),y) (c:cs) "down" (S (x,y) (c:cs) b s)

left :: MyState -> MyState
left (S (_, 0) [_] _ _)= Null
left (S (_, 0) (_:_) _ _)= Null
left (S (x,y) [c] "" s)= S (x,(y-1)) [c] "left" (S (x,y) [c] "" s)
left (S (x,y) [c] b s)= S (x,(y-1)) [c] "left" (S (x,y) [c] b s)
left (S (x,y) (c:cs) "" s)= S (x,(y-1)) (c:cs) "left" (S (x,y) (c:cs) "" s)
left (S (x,y) (c:cs) b s)= S (x,(y-1)) (c:cs) "left" (S (x,y) (c:cs) b s)

right :: MyState -> MyState
right (S (_, 3) [_] _ _)= Null
right (S (_, 3) (_:_) _ _)= Null
right (S (x,y) [c] "" s)= S (x,(y 1)) [c] "right" (S (x,y) [c] "" s)
right (S (x,y) [c] b s)= S (x,(y 1)) [c] "right" (S (x,y) [c] b s)
right (S (x,y) (c:cs) "" s)= S (x,(y 1)) (c:cs) "right" (S (x,y) (c:cs) "" s)
right (S (x,y) (c:cs) b s)= S (x,(y 1)) (c:cs) "right" (S (x,y) (c:cs) b s)

collect:: MyState -> MyState
collect (S l [a,b] d z) | l==a = (S l [b] "collect" (S l [a,b] d z))
                        | l==b = (S l [a] "collect" (S l [a,b] d z))
                        |otherwise =Null


check:: (MyState -> MyState) -> (MyState -> [MyState])
check f (S l [a,b] d z) = if f (S l [a,b] d z) == Null then [] else f (S l [a,b] d z)


nextMyStates:: MyState -> [MyState]
nextMyStates (S l [a,b] d z) = check(up (S l [a,b] d z)    check(down (S l [a,b] d z)    check(right (S l [a,b] d z)    check(left (S l [a,b] d z)   check(collect (S l [a,b] d z)


isGoal :: (MyState) -> (Bool)
isGoal (S l al d z) = if al == ([]) then True else False

search::[MyState]->MyState
search (S l al d z:xs) | isGoal S l al d z =(S l al d z) 
                       | isGoal S l al d z ==False = search xs    nextMyStates (S l al d z)
 


constructSolution :: MyState ->[String]
constructSolution (S l c d z) | z == Null = []
                              | d == Null = []    constructSolution (z p cs s k)
                              | otherwise = [d]     constructSolution (z p cs s k)

solve :: Cell->[Cell]->[String]
solve (x,y) [(a,b),(c,d)] = constructSolution (search (nextMyStates S (x,y) [(a,b),(c,d)] "" Null))

CodePudding user response:

This is way more code than necessary to track down the error. In the future, please include full error messages (those are always useful), but narrow down the code to something more minimal. For example, you can try deleting a function and see if the error still manifests.

Nonetheless, in this case, the issue is not hard to find from the small error message we got: nextMyStates, the function before isGoal, has unbalanced parentheses.

CodePudding user response:

You have unbalanced parens in nextMyStates function. For example you have check(up (S l [a,b] d z) when you probably mean check $ up S l [a,b] d z.

You probably want to read of as-patterns as well, allowing you to simplify your code a lot :)

CodePudding user response:

The nextMyStates definition is the culprit.

nextMyStates (S l [a,b] d z) = check(up (S l [a,b] d z)    check(down (S l [a,b] d z)    check(right (S l [a,b] d z)    check(left (S l [a,b] d z)   check(collect (S l [a,b] d z)

First, let's make that somewhat readable by breaking up the expression instead of having one insanely long line:

nextMyStates (S l [a,b] d z)
  = check(up (S l [a,b] d z)
       check(down (S l [a,b] d z)
       check(right (S l [a,b] d z)
       check(left (S l [a,b] d z)
       check(collect (S l [a,b] d z)

At this point it's obvious that you have done completely unnecessary pattern matching, because the whole S l [a,b] d z is used in all subexpressions. Since this is also the only clause, there's no need for all that verbose stuff: simply match it all as just one variable

nextMyStates s
  = check(up s
       check(down s
       check(right s
       check(left s
       check(collect s

At the latest now it's also obvious what the parse error is: there's a bunch of unmatched parentheses.

nextMyStates s
  = check(up s)
       check(down s)
       check(right s)
       check(left s)
       check(collect s)

This is still unnecessarily verbose: you're doing the same thing a bunch of times, the only difference being the function that's applied to s in each case. When that kind of thing happens, it's usually a good idea to factor out all the repeated parts; one way is to make a list of the functions and then use them in a list comprehension

      [check $ f s | f <- [up, down, right, left, collect]]

Then in the end, to concatenate all the results you can use the concat function:

nextMyStates s = concat [check $ f s | f <- [up, down, right, left, collect]]

BTW isGoal is also stylistically bad. Why do people keep writing if x then True else False? This is silly, it's like saying “the property of the weather being rainy is fulfilled”, instead of simply “the weather is rainy”. The parens are also unnecessary. And for unused variables in a pattern match, convention is to make them all _.

isGoal (S _ al _ _) = al == []

In fact there's also a standard function for (==[]):

isGoal (S _ al _ _) = null al

Alternatively, if you feel you must mention True and False,

isGoal (S _ [] _ _) = True
isGoal _ = False
  • Related