如何编写更短的给定数据类型的显示实例?



我对Haskell很陌生,但我想知道如何编写更短的代码:

data Suite = Club | Heart | Spade | Diamond 
data Value = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | 
King | Ace
data Card = Card Suite Value
instance Show Suite where
show Club = "Club"
show Heart = "Heart"
show Spade = "Spade"
show Diamond = "Diamond"
instance Enum Suite where
enumFromTo Club Diamond = [Club, Heart, Spade, Diamond]
enumFromTo Heart Diamond = [Heart, Spade, Diamond]
enumFromTo Club Spade = [Club, Heart, Spade]
instance Show Value where
show Two = "Two"
show Three = "Three"
show Four = "Four"
show Five = "Five"
show Six = "Six"
show Seven = "Seven"
show Eight = "Eight"
show Nine = "Nine"
show Ten = "Ten"
show Jack = "Jack"
show Queen = "Queen"
show King = "King"
show Ace = "Ace"

我想更短地编写显示值的实例。有没有好方法可以做到这一点,或者我需要写所有? 我也想知道如果我想为 Eq 卡、普通卡定义相同的实例,我该如何从这里开始? 迄今

instance Eq Card where
Card _ _ == _ = False
instance Ord Card where
Card Heart Three > Card Heart Two = True

有效,但要编写每一种可能性将是相当多的工作。 感谢您的任何回答!

编辑:我知道附加派生(显示等(的可能性,但我不想使用它

您已经拒绝了这些实例deriving,这是我们避免那么多样板的主要方法。缩短Show Value的最明显的基本方法是使用case表达式。这使用额外的行,但略微缩短了每个情况:

instance Show Value where
show x = case x of
Two -> "Two"
Three -> "Three"
-- etc.

扩展到非基本方式,您可以

  1. 使用泛型,要么是GHC.Generics中更现代的版本,要么是Data.Data中的版本(在这种情况下可能更容易(。对于这些,您分别需要deriving Genericderiving Data,然后您可以编写(或在 Hackage 上挖掘(您需要的类方法的通用版本。这两种方法似乎都不太适合Haskell初学者,但您可以在几个月内练习它们。

  2. 使用模板哈斯克尔。这是一个非常高级的语言功能,尽管与Haskell合作多年,但我还没有真正开始掌握如何使用它进行编程。祝你好运!

如果您只想让show方法调用打印构造函数的名称(如此处所示(,则根本不需要手动实例化它们。您可以这样自动派生Show实例:

data Suit = Club | Heart | Spade | Diamond
deriving Show
data Value = Two | Three | Four | Five | Six | Seven 
| Eight | Nine | Ten | Jack | Queen | King | Ace
deriving Show

在某些情况下,例如Instance Show Value,没有deriving就没有好方法可以缩短它(不包括 dfeuer 答案中的那些(。

但在其他人中,有!

例如
  1. 对于Enum实例,定义fromEnumtoEnum就足够了,其余的都有默认定义。您当然不需要像示例代码那样enumFromTo列出所有可能性。

  2. 定义instance Enum Value后,可以通过转换为Int并比较结果来编写比较函数:

    instance Eq Value where
    x == y = fromEnum x == fromEnum y
    instance Ord Value where
    compare x y = compare (fromEnum x) (fromEnum y)
    
  3. 在为Card编写定义时,您可以使用实例进行ValueSuit,例如

    instance Eq Card where
    Card s1 v1 == Card s2 v2 = s1 == s2 && v1 == v2
    

最新更新