[Haskell-cafe] Trouble with indentation

Jules Bean jules at jellybean.co.uk
Wed Jan 9 07:13:23 EST 2008


Fernando Rodriguez wrote:
> 
> Hi,
> 
> I'm trying to write a function that finds out the week day using the 
> Zeller congruence (http://en.wikipedia.org/wiki/Zeller's_congruence).
> 
> However, ghc complains about: parse error on input `=' at the "if m <= 2 
> then " line. I believe this is some sort of layout error.  Can someone 
> point out what I am doing wrong?
> 
> Here's the code:
> 
> data DiaSemana = Lunes | Martes | Miercoles | Jueves | Viernes
>                 | Sabado | Domingo deriving (Show, Eq, Ord, Enum)
> diaDeSemana d m a = toEnum num :: DiaSemana
>                     where
>                         num = zeller x y z
>                         zeller x y z = (700 + (26 * x - 2) `div` 10
>                              + d + y + y `div` 4 + z `div` 4 - 2 * z)
>                              `mod` 7
>                         if m <= 2 then                             x = m 
> + 10
>                             y = (a - 1) `mod` 100
>                             z = (a-1) 'div' 100
>                         else                             x = m - 2
>                             y = a  `mod` 100
>                             z = a `div` 100


That looks like it's been mangled a bit by your mail program or mine, 
but anyway:

This is not a layout problem. The problem here is simply that you can't 
put "ifs" around chunks of definitions. "if" is an expression level 
concept, not a definition-level one.

You could try:

diaDeSemana d m a = toEnum num :: DiaSemana
                     where
                         num = zeller x y z
                         zeller x y z = (700 + (26 * x - 2) `div` 10
                              + d + y + y `div` 4 + z `div` 4 - 2 * z)
                              `mod` 7
                         x | m <= 2    = m + 10
                           | otherwise = m - 2
                         y | m <= 2    = (a - 1) `mod` 100
                           | otherwise = a  `mod` 100
                         z | m <= 2    = (a-1) 'div' 100
                           | otherwise = a `div` 100


or, to avoid the ugly duplication of the m <= 2 constraint, we can use 
an if in an expresson like this:

diaDeSemana d m a = toEnum num :: DiaSemana
                     where
                         num = zeller x y z
                         zeller x y z = (700 + (26 * x - 2) `div` 10
                              + d + y + y `div` 4 + z `div` 4 - 2 * z)
                              `mod` 7
                         (x,y,z) = if m <=2 then
                                      (m+10,(a-1)`mod`100,(a-1)`div`100)
                                   else
                                      (m-2,a`mod`100,a`div`100)


... or, replacing the if with guards again ...

diaDeSemana d m a = toEnum num :: DiaSemana
                     where
                      num = zeller x y z
                      zeller x y z = (700 + (26 * x - 2) `div` 10
                           + d + y + y `div` 4 + z `div` 4 - 2 * z)
                           `mod` 7
                      (x,y,z)
                        | m <=2     = (m+10,(a-1)`mod`100,(a-1)`div`100)
                        | otherwise = (m-2 ,a    `mod`100,a    `div`100)

Jules


More information about the Haskell-Cafe mailing list