我有一段代码,我在其中声明了两种数据类型。我已经自动派生为类型类enum
的成员,但是,我不喜欢它们不是"循环"。这样,我的意思是调用succ Sun
应该让我Mon
。 succ 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)是唯一改变的变量。
答案 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)
如果您启用FlexibleInstances
和UndecidableInstances
扩展程序,则可以执行以下操作:
{-# 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