我刚刚开始学习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)
我究竟做错了什么?有没有其他方法来构建这种类型?
非常感谢你的回答!
扩展我的评论:
我很确定你不能只有数字组成的名字.如果你真的想按自己的方式去做,你可以做到
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功能,确保不会产生奇怪的周数.