Haskell: получить имя конструктора данных как строку

Скажем, мы имеем

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

Я хочу иметь функцию getDConst

getDConst :: D -> String

который возвращает либо "X", "Y", либо "Z", в соответствии с конструктором данных, используемым для его ввода. Есть ли общий способ написать это, не делая case для каждого конструктора данных? (Я в порядке с решениями, основанными на Data.Typeable или чем-то подобном)

Ответ 1

Нашел решение самостоятельно, но оставив этот вопрос, чтобы помочь другим:

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

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

Ответ 2

Если вы не хотите использовать Typeable, вы также можете сделать это с помощью Show.

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

Show не выводит все поля, потому что он ленив. Вы можете проверить его запуск этого кода в ghci:

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

Ответ 3

Как отметил Николас Хенин в комментарии, другие упомянутые решения опираются на стандартную реализацию Show. Лучшим подходом является тот, который описан на fooobar.com/info/2448128/....