简体   繁体   English

Haskell中的类型声明问题

[英]A question of Type declaration in Haskell

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我以为我可以写一个func来使用+,例如: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:但是ghci说它有一个错误:

? 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但是我仍然不知道“Day -> Int -> Day”有什么问题......请帮助

When you define a function named (+) , you are shadowing Prelude's addition function.当您定义一个名为(+)的 function 时,您将隐藏 Prelude 的添加 function。 In the body of (+):: Day -> Int -> Day , you evaluate (y + 1) , expecting an Int .(+):: Day -> Int -> Day的正文中,您评估(y + 1) ,期待Int But this new (+) function returns a Day !但是这个新的(+) function 返回了Day The more polymorphic version for Enum works, because Int has an Enum instance, and so (+) can be used on both types. Enum的多态版本有效,因为Int有一个Enum实例,因此(+)可以用于两种类型。

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) .或者,当您想使用新的(+)时,您可以在递归调用中明确表示,而当您想使用原始调用时,可以通过编写(y Prelude.+ 1)来明确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM