2013-08-18 20 views
11

Powiedzmy mamyHaskell: Get nazwisko konstruktora dane jako ciąg

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

pragnę mieć funkcję getDConst

getDConst :: D -> String 

która zwraca albo "X", "Y" lub " Z ", zgodnie z konstruktorem danych użytym do jego wprowadzenia. Czy istnieje ogólny sposób pisania tego bez konieczności wykonywania case na każdym konstruktorze danych? (Jestem ok z rozwiązań opierając się na Data.Typeable lub coś podobnego)

Odpowiedz

13

znalazł rozwiązanie siebie, ale pozostawiając tę ​​kwestię do pomagania innym:

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

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

Jeśli ktoś dostaje też błąd z tym: Spróbuj dodać '{- # JĘZYK DeriveDataTypeable # -}' na początku pliku. Jest to konieczne w GHC, gdy czerpiesz dane i można je wydobywać. – jPlatte

6

Jeśli nie chcesz używać Typeable, można również zrób to z Show.

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

nie wyświetli wszystkich pól, ponieważ jest leniwy. można go przetestować runiczny ten kod w ghci:

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

Możesz także chcieć zaimplementować niestandardowe wyjście pokazu, które nie obejmuje konstruktora. – kqr

+0

'show' jest leniwy, więc to prawdopodobnie nie będzie bardzo powolne. Zauważ, że 'take 5 (show (Just undefined)) działa dobrze. –

+2

Masz na myśli 'słowa', a nie' unwords'. (Właściwie to piszę coś w stylu 'takeWhile (/ = ''). Show') – Lynn