5

我遵循 Haskell 的 Wiki 页面上的建议:性能/数据类型以提高我的代码的性能,但是当我改变时

data Color = Yellow | Red | Green | Blue | Empty deriving (Show, Eq)

newtype Color = Color Int deriving (Eq,Ord,Enum) 
(yellow:red:green:blue:empty:_) = [Color 1 ..]

正如文章中所建议的,GHC 说:

Can't make a derived instance of `Enum Color':
  `Color' must be an enumeration type
  (an enumeration consists of one or more nullary, non-GADT constructors)
  Try -XGeneralizedNewtypeDeriving for GHC's newtype-deriving extension
In the newtype declaration for `Color'

我没有太多使用 Enums,如何将 Color 转换为 Enum 类型?我必须实现它定义的所有功能吗?我认为当您派生该类时它们都已实现。

4

2 回答 2

10

有时 GHC 的建议很糟糕,但在这种情况下,它是正确的。在文件的顶部,放

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

GeneralizedNewtypeDeriving是一种语言扩展,允许您指定某些类应“转发”到其表示的实例。也就是说,仅通过使用 'snewtype Color = Color Int deriving (Enum)来实现Color'sEnum实例Int(在 GHC 为您生成的一些必要的包装/解包之后)。

但如果这是您需要的唯一原因Enum,您也可以省略它并直接执行

(yellow:red:green:blue:empty:_) = map Color [1..]
于 2012-12-07T10:30:20.817 回答
4

请注意,通过派生Enum,您只会得到部分正确的实现。例如,enumFrom yellow将返回一个等同于 的列表map Color $ [1..],这可能不是您想要的。

所以我宁愿建议EnumBounded手动一起实现,这样它就可以满足文档中给出的规则Enum

我想所有这些东西都可以用Template Haskell自动生成。这将成为一个有趣的库。

于 2012-12-07T12:07:56.643 回答