tohava
tohava

Reputation: 5412

Haskell: Get data constructor name as string

Let us say we have

data D = X Int | Y Int Int | Z String

I wish to have a function getDConst

getDConst :: D -> String

that returns either "X", "Y", or "Z", according to the data constructor used for its input. Is there a generic way to write this without having to do case on every data constructor? (I am ok with solutions relying on Data.Typeable or something similar)

Upvotes: 25

Views: 3729

Answers (3)

superlinux
superlinux

Reputation: 470

I have a much basic answer to the question without going through imports or whatever. It's Just a simple mere function.

let's say I have the following data. The repetitive Int in the data definition is intentional because I will use the don't care symbol afterwards:

data YES_NO_CANCEL = YES Int | NO Int Int | CANCEL Int Int Int

then you can make a function as :

extractDataType :: YES_NO_CANCEL -> String
extractDataType (YES _) = "YES"
extractDataType (NO _ _) = "NO"
extractDataType (CANCEL _ _ _) = "CANCEL"

Upvotes: -1

MathematicalOrchid
MathematicalOrchid

Reputation: 62848

If you don't want to use Typeable, you can also do this with Show.

getDConst :: D -> String
getDConst = head . words . show

Show will not output all the fields, because it is lazy. You can test it runing this code in ghci:

Prelude> data D = D [Int] deriving (Show)
Prelude> getDConst $ D [1..]
"D"

Upvotes: 11

tohava
tohava

Reputation: 5412

Found the solution myself, but leaving this question to help others:

import Data.Data
data D = X Int | Y Int Int deriving (Data,Typeable)

let result = show $ toConstr (X 3) -- result contains what we wanted

Upvotes: 26

Related Questions