简体   繁体   English

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

[英]Getting a list of all possible data type values in Haskell

If I have a data type say: 如果我有数据类型,请说:

data Color = Red | Yellow | Green

Is there a way I can turn this into a list of type [Color] getting all possible values? 有没有办法将其转换为[Color]类型的列表,以获取所有可能的值? [Red, Yellow, Green] [红色,黄色,绿色]

Perhaps this is a complete anti pattern? 也许这是一个完整的反模式?

Not sure if it is an anti-pattern (nor can I think of a good use right now), but it's possible. 不知道它是否是反模式(我现在也不能想到一个很好的用法),但是有可能。 Use the Enum (allows to generate a list like [someCtor .. someOtherCtor] ) and Bounded (for minBound and maxBound ) type classes. 使用Enum (允许生成类似[someCtor .. someOtherCtor]的列表)和Bounded (对于minBoundmaxBound )类型类。 Luckily, you can derive both: 幸运的是,您可以同时导出:

data Color = Red
           | Yellow
           | Green
           deriving (Enum, Bounded)

allColors = [(minBound :: Color) ..]

If you ever add another color, allColors get updated automatically. 如果您添加其他颜色,则allColors将自动更新。 One restriction though: Enum requires all contructors to be nullary, ie adding Foo Int breaks the whole thing. 但是有一个限制: Enum要求所有构造函数均为零,即,添加Foo Int会破坏整个过程。 Luckily, because a list of all possible values for this would be way too large. 幸运的是,因为所有可能的值列表太大了。

Edit: The other answer works as well, maybe better since it doesn't require deriving Bounded and is therefore a bit shorter. 编辑:另一个答案也很好,也许更好,因为它不需要派生Bounded ,因此要短一些。 I'll still leave mine because I love over-engineered but extremely generic code ;) 我仍然会离开我,因为我喜欢过度设计但极其通用的代码;)

Surely delnan's answer is better. 当然,德尔南的答案更好。 Since I do not know how to include a piece of code in a comment, I'll give a generalisation as a separate answer here. 由于我不知道如何在注释中包含一段代码,因此在这里我将给出一个概括作为单独的答案。

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

Now, this works for any type with a Bounded and Enum instance! 现在,此方法适用于具有BoundedEnum实例的任何类型! And allColors is just a special case: allColors只是一个特例:

allColors :: [Color]
allColors = allValues

In many cases, you won't even need to define allColors separately. 在许多情况下,您甚至不需要单独定义allColors

data Color = Red
           | Yellow
           | Green
           deriving Enum

allColors = [Red ..]

Here is an example of using this technique to parse enums with Parsec 这是使用此技术通过Parsec解析枚举的示例

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

And the parsec parser 和parsec解析器

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

of course the try could could be applied by better by pattern matching and a few other things could make it nicer but this is just an example of some usage of the technique. 当然,可以通过模式匹配来更好地应用尝试,而其他一些事情可能会使它变得更好,但这只是该技术的一些使用示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM