Getting a list of all possible data type values in Haskell

前端 未结 4 1981
一整个雨季
一整个雨季 2020-12-06 04:06

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 possibl

相关标签:
4条回答
  • 2020-12-06 04:20

    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. 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. One restriction though: Enum requires all contructors to be nullary, i.e. adding Foo Int breaks the whole thing. 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. I'll still leave mine because I love over-engineered but extremely generic code ;)

    0 讨论(0)
  • 2020-12-06 04:28

    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! And allColors is just a special case:

    allColors :: [Color]
    allColors = allValues
    

    In many cases, you won't even need to define allColors separately.

    0 讨论(0)
  • 2020-12-06 04:40

    Here is an example of using this technique to parse enums with Parsec

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

    And the parsec parser

    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.

    0 讨论(0)
  • 2020-12-06 04:46
    data Color = Red
               | Yellow
               | Green
               deriving Enum
    
    allColors = [Red ..]
    
    0 讨论(0)
提交回复
热议问题