在Haskell中键入整数的构造函数

1 haskell types typeclass

我刚刚开始学习Haskell,我遇到了以下问题:

我想创建一个日历周的类型,即从1到52的数字.这就是我尝试这个的原因:

data CalendarWeek = 1 | 2 | ... | 52 deriving (Eq, Order, Show)
Run Code Online (Sandbox Code Playgroud)

那么它可以在这里使用:

data Offer = Offer CalendarWeek Day Offer String deriving (Eq, Order, Show)
Run Code Online (Sandbox Code Playgroud)

但是,GHC只打印出以下错误:

parse error on input `1'
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?有没有其他方法来构建这种类型?

非常感谢你的回答!

kqr*_*kqr 5

扩展我的评论:

我很确定你不能只有数字组成的名字.如果你真的想按自己的方式去做,你可以做到

data CalendarWeek = W1 | W2 | W3 | … | W52 | W53 deriving (Eq, Order, Show)
Run Code Online (Sandbox Code Playgroud)

(请记住,有些年份有53周,最后一次是2009年.)

但是,我不推荐这个.首先,它是大量的打字,无论如何,在以这种方式做事时,很难将周数视为数字.我建议做的是

data CalendarWeek = Week Int
Run Code Online (Sandbox Code Playgroud)

然后你可以定义一个像这样的函数

mkWeek :: Int -> CalendarWeek
mkWeek number =
  if number >= 1 && number <= 53
     then Week number
     else error "Not a valid week number!"
Run Code Online (Sandbox Code Playgroud)

这将导致mkWeek 47返回值Week 47,同时mkWeek 112会使程序崩溃.在一个真实的程序中,你可能不想在这里吹你的程序,但你做的是取决于情况.

同样,每当你工作几周时,你需要确保价值不会溢出,但这是微不足道的(如果你通过mkWeek,你可以免费获得支票!)

当然,为了使您的方法与您建议的方法一样安全,您需要编写一堆测试.应该测试处理周数的所有函数,以便它们不会意外返回Week 975.而且,如果你设计这个作为一个单独的模块,你应该导出Week的构造函数,因为这样做会允许任何人创建的任何疯狂的一周值.相反,强迫每个人使用你的mkWeek功能,确保不会产生奇怪的周数.