Reputation: 888
I have a simple data type such as:
data Class = Class1
| Class2
| Class3
deriving (Show, Eq)
Is there a simple way for me to build a list of Strings that contains the String version of each of these such that:
func Class = ["Class1", "Class2", "Class3"]
Upvotes: 1
Views: 70
Reputation: 32319
The answer is yes, but with a caveat. What is the type of func
? It looks like its first argument would be a type, not a value. More on the later...
Deriving Enum
gets you get the ability to list off successive constructors and deriving Bounded
gets you the ability to get the "first" and "last" elements of this enumeration.
data Class = Class1
| Class2
| Class3
deriving (Show, Eq, Enum, Bounded)
Then, we can get a list of all the elements via enumFromTo minBound maxBound
(or just [minBound .. maxBound]
).
However, back to the initial question on the type of func
. You need to pass in a type as an argument. The usual way of doing this is using Proxy
and ScopedTypeVariables
.
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Proxy (Proxy(..))
func :: forall a. (Enum a, Bounded a, Show a) => Proxy a -> [String]
func Proxy = map show $ enumFromTo minBound (maxBound :: a)
Try this out at GHCi:
ghci> func (Proxy :: Proxy Class)
["Class1","Class2","Class3"]
ghci> func (Proxy :: Proxy Bool)
["True","False"]
Upvotes: 5
Reputation: 233192
You could, perhaps, do something like this:
data Class = Class1 | Class2 | Class3 deriving (Show, Eq, Enum)
GHCI:
Prelude> fmap show $ enumFrom Class1
["Class1","Class2","Class3"]
Upvotes: 3