0

I am fairly new to Haskell and am working on an assignment simulating checkers currently. I am having a bit of difficulty determining the proper method of conditionally checking an expression and updating the values of a tuple. I have a function called getPos that will return the Char at a specific location on the board to determine its state.

    onemove :: (Int,[Char],[[Char]],(Int,Int)) -> (Int,[Char],[[Char]])

    onemove     (a,b,c,(d,e)) 
       | e <= 0 =(a-30,b,c)
       | e > 50 =(a-30,b,c)
       | (((posTo == 'r') || (posTo == 'i')) &&((posFrom == 'w')||(posFrom == 'k'))) == 'true'  =(a-20,b,c)
       | (((posTo == 'w')||(posTo == 'k')) && ((posFrom == 'r') || (posFrom == 'i')))== 'true' =(a-20,b,c)
       | otherwise = (1000,b,c)
       where posFrom = getPos (d, c)
             posTo =  getPos (e,c)

Is it correct to use a function to define a variable within my where clause? I receive the following error on my last line:

    parse error on input `='
hashes4merkle
  • 352
  • 3
  • 11
  • I don't even reach that point. I get a `parse error on input \`|'` on the first guard (what you call 'conditional' is actually called a 'guard', 'guarded statement', or anything along those lines). Indentation matters in Haskell; all those pipe characters and the `where` need to move at least one column to the right. –  Aug 09 '14 at 15:29

1 Answers1

6

Your immediate problem is mostly just caused by indentation. Guards need to be indented w.r.t the definition they're associated with.

onemove :: (Int,[Char],[[Char]],(Int,Int)) -> (Int,[Char],[[Char]])
onemove     (a,b,c,(d,e)) 
  | e <= 0 =(a-30,b,c)
  | e > 50 =(a-30,b,c)
  | (((posTo == 'r') || (posTo == 'i')) &&((posFrom == 'w')||(posFrom == 'k'))) =(a-20,b,c)
  | (((posTo == 'w')||(posTo == 'k')) && ((posFrom == 'r') || (posFrom == 'i'))) =(a-20,b,c)
  | otherwise = (1000,b,c)
  where posFrom = getPos (d, c)
        posTo =  getPos (e,c)

Notice I also removed the == 'true' in your original code. That was wrong for three separate reasons.

  1. Single quotes denote a Char. Double quotes for String.
  2. You can't compare a Boolean value to a String just because that String happens to say "true". You would have to say == True.
  3. There's no reason to ever write bool == True, because that's exactly the same as just writing bool.

Also, a, b, c, and (d,e) should probably all be separate arguments, not a single tuple. You lose all the advantages of currying that way.

Mark Whitfield
  • 2,470
  • 1
  • 12
  • 12
  • 1
    It seems that `(a,b,c)` together acts as some sort of environment, so they probably belong together. But OP should really consider using `data` for that. (I'm starting to think that even tuples may be harmful when learning Haskell.) –  Aug 09 '14 at 15:34
  • I appreciate the help! I think the indentation problem came in as I was copying into stackOverflow. As @Rhymoid mentioned, the tuple is a set environment so I am unable to adjust the data structure. With the follow declaration for getPos: `getPos :: Int -> [[Char]] -> Char`, what is the cause of a `Couldn't match expected type 'Int'` error? Thanks guys – hashes4merkle Aug 09 '14 at 15:42
  • Well, as you just wrote, getPos expects and `Int` and a `[[Char]]` but you handed it an `(Int,[[Char]])`. You want `getPos d c` not `getPos (d,c)`. – Mark Whitfield Aug 09 '14 at 15:46
  • That was my issue. Thanks mark! you've cleared up a few questions I've been scratching my head over. – hashes4merkle Aug 09 '14 at 16:00