3

LYAH派生实例上说

[...] 所有的值构造函数都是空的(不带参数,即字段),我们可以将其作为 Enum 类型类的一部分。

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

现在,如果我需要几个月,那将是

data month = January | February | March | April | May | June | July | August |September | October | November |December     
deriving (Eq, Ord, Show, Read, Bounded, Enum)

我的问题是:

  1. 每个月在哪里存储 Max Days 值?
  2. 如果是闰年,如何提及和控制二月份的月份,那么二月份的 maxDays 是 29 天,否则它将是 28 天?

在 Java 中,可以编写如下代码:

public enum Month {  
    January (31),  
    February (29),  
    March (31),  
    April (30),  
    May (31),  
    June (30),  
    July (31),  
    August (31),  
    September (30),           
    October (31),  
    November (30),  
    December (31),  
    ;  
    private int maxDays; // instance variables  
    private (int maxDays) { // constructors always private  
           this.maxDays = maxDays;  
    }  
    Public int getMaxDays () {  
       return maxDays;  
    }
4

2 回答 2

7

这应该有效。

data Month = January | February | March | April | May
           | June | July | August |September | October
           | November | December
           deriving (Eq, Ord, Show, Read, Bounded, Enum)

type Year = Int

isLeapYear :: Year -> Bool
isLeapYear year = year `mod` 4 == 0 && (year `mod` 100 /= 0 || year `mod` 400 == 0)

getMaxDays :: Year -> Month -> Int
getMaxDays _ January = 31

getMaxDays year February
    | isLeapYear year = 29
    | otherwise = 28

getMaxDays _ March = 31
getMaxDays _ April = 30
getMaxDays _ May = 31
getMaxDays _ June = 30
getMaxDays _ July = 31
getMaxDays _ August = 31
getMaxDays _ September = 30
getMaxDays _ October = 31
getMaxDays _ November = 30
getMaxDays _ December = 31
于 2012-07-26T04:03:43.940 回答
7

为什么你需要Month成为一个枚举?在我看来,您试图在代码中强制使用 OO 样式,这不是一个好主意。Java 面向对象的代码编写风格并不能清晰地转换为 Haskell 等函数式语言。

在 OO 中,您会将数据结构和对该数据的所有关联操作捆绑在一个类中,而在 FP 中,您将与关联操作分开定义数据结构。这意味着 FP 方法可以更轻松地定义对数据的新操作,而 OO 方法可以更轻松地将新信息添加到数据结构中。就个人而言,我发现自己定义新操作比添加新字段和 FP 风格套装要多得多。

与 Haskell 中的 Java 示例最接近的类似物是定义一个 Typeclass -

data Month = January | February | March | April
           | May | June | July | August |September
           | October | November |December
  deriving (Eq, Ord, Show, Read, Bounded, Enum)

data Year = Int

class HasDays X where
  maxdays :: X -> Int
  days    :: X -> Year -> Int
  -- Any other "methods" here

instance HasDays Month where
  maxdays January = 31
  maxdays February = 29
  maxdays .. = .. -- Similar code for other months

  days February y = .. -- Leap year calculation
  days m _ = maxdays m
于 2012-07-26T06:40:23.990 回答