制作“循环”枚举类型类的实例的冗余方法较少

时间:2013-11-29 22:40:51

标签: haskell types functional-programming

我有一段代码,我在其中声明了两种数据类型。我已经自动派生为类型类enum的成员,但是,我不喜欢它们不是"循环"。这样,我的意思是调用succ Sun应该让我Monsucc Dec会产生Jan。因此,我没有写自己的枚举,而是这样做了:

data WeekDay = Mon | Tue | Wed | Thu | Fri | Sat | Sun
             deriving (Enum, Show, Eq, Bounded)

data Month = Jan | Feb | Mar | Apr | May | Jun | July | Aug | Sep | Oct | Nov 
             | Dec
           deriving (Enum, Show, Eq, Bounded)

class Circ a where
  next :: Enum a => a -> a

instance Circ WeekDay where
  next a = if a == maxBound then minBound else succ a

instance Circ Month where      -- this is nearly identical to the one above
  next a = if a == maxBound then minBound else succ a

我的问题是:是否有更整洁,更少冗余的写作方式?换句话说,我写了两个几乎相同的实例,数据类型名称(WeekDay vs. Month)是唯一改变的变量。

4 个答案:

答案 0 :(得分:10)

class (Enum a, Bounded a, Eq a) => Circ a where
     next :: a -> a
     next a = if a == maxBound then minBound else succ a

instance Circ WeekDay
instance Circ Month

答案 1 :(得分:4)

我想建立Ingo的答案,指出你根本不需要定义一个类型类。您可以在不调用任何其他类型类的情况下定义以下函数:

next :: (Eq a, Bounded a, Enum a) => a -> a
next a = if a == maxBound then minBound else succ a

现在您不必为所有类型声明instance Circ

答案 2 :(得分:2)

如果您启用FlexibleInstancesUndecidableInstances扩展程序,则可以执行以下操作:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}

instance (Eq a, Bounded a, Enum a) => Circ a where
  next e = if e == maxBound then minBound else succ e

答案 3 :(得分:2)

您也可以添加prev

class (Enum a, Bounded a, Eq a) => Circ a where
     next :: a -> a
     next a = if a == maxBound then minBound else succ a
     prev :: a -> a
     prev a = if a == minBound then maxBound else pred a