haskell - 如何为自定义数据类型定义 (+) 函数?

我是新人,从书中学习:

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

我想我可以写一个 func 来使用 +,例如:Monday + 1 = Tuesday

所以:

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

但是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

我不知道为什么,但我尝试了另一个:

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

效果不错,比如:

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

但我仍然不知道 Day -> Int -> Day 有什么问题。

最佳答案

当您定义一个名为 (+) 的函数时,您正在隐藏 Prelude 的加法函数。在 (+)::Day -> Int -> Day 的主体中,您计算​​ (y + 1),期望得到一个 Int。但是这个新的 (+) 函数返回一个 Day! Enum 的多态版本可以工作,因为 Int 有一个 Enum 实例,所以 (+) 可以是用于两种类型。

要解决这个问题,您可以简单地为该操作指定一个新名称,而不是隐藏 (+)。或者,当您想使用新的 (+) 时,您可以通过编写 (y Prelude.+ 1) 来明确递归调用。

https://stackoverflow.com/questions/70528861/

相关文章:

node.js - 带有 Webpack 的 Electron 原生 NodeJS 模块

python - 如何解析 (1045, "Access denied for user ' Use

c++ - 即使在手动设置显示环境变量后,WSL Ubuntu 仍显示 "Error: Unable

r - 是否可以将变量从全局环境移动到单独的环境中?

julia - 如何在 Julia 中绘制复数?

android - Appium 创建 session 失败

c# - Entity Framework 排序列表

r - 从向量中提取字符元素

c++ - 使用 C++ 生成真正的随机数 (Windows 10 x64)

javascript - 一键执行两个功能