Home > Enterprise >  A question of Type declaration in Haskell
A question of Type declaration in Haskell

Time:12-30

I'm a new one And study from book:

data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord, Show, Read, Bounded, Enum)

I thought that I can write a func to use , example: Monday 1 = Tuesday

So:

:{                           
( ) :: Day -> Int -> Day     
( ) x y                      
  | y>0 = ( ) (succ x) (y-1) 
  | y<0 = ( ) (pred x) (y 1) 
  | y==0 = x                 
:}   

But ghci said it has a mistake:

? Couldn't match expected type ‘Int’ with actual type ‘Day’
? In the second argument of ‘( )’, namely ‘(y   1)’
  In the expression: ( ) (pred x) (y   1)
  In an equation for ‘ ’:
      ( ) x y
        | y > 0 = ( ) (succ x) (y - 1)
        | y < 0 = ( ) (pred x) (y   1)
        | y == 0 = x

I don't know why but I tried another one:

:{                                
( ) :: (Enum a) =>  a -> Int -> a 
( ) x y                           
  | y>0 = ( ) (succ x) (y-1)      
  | y<0 = ( ) (pred x) (y 1)      
  | y==0 = x                      
:}                                

It works well, like:

ghci> Monday   1     
Tuesday              
ghci> Monday   3     
Thursday             
ghci> Thursday   (-2)
Tuesday              

But I still don't know what's wrong with "Day -> Int -> Day"... Please help

CodePudding user response:

When you define a function named ( ), you are shadowing Prelude's addition function. In the body of ( ) :: Day -> Int -> Day, you evaluate (y 1), expecting an Int. But this new ( ) function returns a Day! The more polymorphic version for Enum works, because Int has an Enum instance, and so ( ) can be used on both types.

To get around this, you could simply give this operation a new name instead of shadowing ( ). Or, you could be explicit in the recursive call when you want to use your new ( ) and when the original one, by writing (y Prelude. 1).

  • Related