FutureShocked
FutureShocked

Reputation: 888

Can I build a list of Strings using each constructor of a class?

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

Answers (2)

Alec
Alec

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

Mark Seemann
Mark Seemann

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

Related Questions