Cilenco
Cilenco

Reputation: 7117

Haskell method with two where clauses

I want to write a Haskell function which has two where clauses but I get this error from the compiler:

Syntax error in input (unexpected symbol "changeNew")

changeItem oPos nPos (x:xs) 
                        | oPos < nPos = changeOld
                        | oPos > nPos = changeNew
                        | otherwise = x : changeItem (oPos-1) (nPos-1) xs
                        where changeOld
                            | oPos == 0 = (xs !! nPos) : changeItem x (nPos-1) xs
                            | nPos == 0 = oPos : xs
                            | otherwise = x : changeItem (oPos-1) (nPos-1) xs
                        changeNew
                            | oPos == 0 = nPos : xs
                            | nPos == 0 = (xs !! oPos) : changeItem (oPos-1) x xs
                            | otherwise = x : changeItem (oPos-1) (nPos-1) xs

What is wrong with the code? Why can't I declare two where clauses?

Upvotes: 2

Views: 180

Answers (2)

Chris Taylor
Chris Taylor

Reputation: 47382

The names being defined in the where clause need to line up on the left-hand side, like this

changeItem oPos nPos (x:xs) 
                        | oPos < nPos = changeOld
                        | oPos > nPos = changeNew
                        | otherwise = x : changeItem (oPos-1) (nPos-1) xs
                        where 
                          changeOld
                            | oPos == 0 = (xs !! nPos) : changeItem x (nPos-1) xs
                            | nPos == 0 = oPos : xs
                            | otherwise = x : changeItem (oPos-1) (nPos-1) xs
                          changeNew
                            | oPos == 0 = nPos : xs
                            | nPos == 0 = (xs !! oPos) : changeItem (oPos-1) x xs
                            | otherwise = x : changeItem (oPos-1) (nPos-1) xs

Although a more "usual" Haskell style would move everything to the left, to prevent your code marching off into the bottom right hand corner.

changeItem oPos nPos (x:xs) 
  | oPos < nPos = changeOld
  | oPos > nPos = changeNew
  | otherwise = x : changeItem (oPos-1) (nPos-1) xs
 where 
  changeOld
    | oPos == 0 = (xs !! nPos) : changeItem x (nPos-1) xs
    | nPos == 0 = oPos : xs
    | otherwise = x : changeItem (oPos-1) (nPos-1) xs
  changeNew
    | oPos == 0 = nPos : xs
    | nPos == 0 = (xs !! oPos) : changeItem (oPos-1) x xs
    | otherwise = x : changeItem (oPos-1) (nPos-1) xs

Upvotes: 10

Chuck
Chuck

Reputation: 237010

Your indentation is wrong. changeNew needs to line up with changeOld rather than with where.

Upvotes: 0

Related Questions