代码之家  ›  专栏  ›  技术社区  ›  Guy

获取Haskell中所有可能的数据类型值的列表

  •  32
  • Guy  · 技术社区  · 14 年前

    如果我有数据类型,请说:

    data Color = Red | Yellow | Green
    

    有没有办法把它变成一个列表类型[颜色]来获取所有可能的值?[红,黄,绿]

    也许这是一个完全的反模式?

    4 回复  |  直到 14 年前
        1
  •  34
  •   ase    14 年前
    data Color = Red
               | Yellow
               | Green
               deriving Enum
    
    allColors = [Red ..]
    
        2
  •  58
  •   user395760user395760    14 年前

    不确定这是否是一种反模式(我现在也不能想出好的用法),但这是可能的。使用 Enum (允许生成如下列表 [someCtor .. someOtherCtor] )以及 Bounded (用于 minBound maxBound )类型类。幸运的是,你可以得到:

    data Color = Red
               | Yellow
               | Green
               deriving (Enum, Bounded)
    
    allColors = [(minBound :: Color) ..]
    

    如果您添加了其他颜色,所有颜色都会自动更新。但有一个限制: 枚举 要求所有构造函数都为空,即添加 Foo Int 破坏了整件事。幸运的是,因为所有可能值的列表都太大了。

    编辑:另一个答案也可以,也许更好,因为它不需要派生 有界的 因此它有点短。我还是会离开我的,因为我喜欢过度工程化但非常通用的代码;)

        3
  •  40
  •   stusmith    14 年前

    德尔南的回答当然更好。因为我不知道如何在注释中包含一段代码,所以我将在这里给出一个概括的答案。

    allValues :: (Bounded a, Enum a) => [a]
    allValues = [minBound..]
    

    现在,这适用于任何类型 Bounded Enum 实例!以及 allColors 只是个特例:

    allColors :: [Color]
    allColors = allValues
    

    在很多情况下,你甚至不需要定义 五颜六色 另外。

        4
  •  3
  •   Eric    13 年前

    下面是一个使用此技术使用Parsec解析枚举的示例

    data FavoriteColor = Maroon | Black | Green  | Red | 
                         Blue   | Pink  | Yellow | Orange
                                 deriving (Show, Read, Enum, Bounded)
    

    语法分析器

    parseColor :: Parser FavoriteColor           
    parseColor = fmap read . foldr1 (<|>) $ map (try . string . show) 
      [ minBound :: FavoriteColor ..] 
    

    当然,这种尝试可以通过模式匹配得到更好的应用,还有一些其他的东西可以使它变得更好,但这只是某种技术使用的一个例子。