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