2013-08-18 15 views
11

としてデータコンストラクタ名を取得する私は、 "X"、 "Y"、または「どちらかを返す関数getDConstハスケル:文字列

getDConst :: D -> String 

を持つことを望む私たちは

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

を持っているとしましょうZ "に変換されます。すべてのデータコンストラクタでcaseを実行することなくこれを書く一般的な方法はありますか?

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

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

答えて

13

がソリューションを自分で見つけましたが、他の人を助けるためにこの質問を残して(私は解決策がData.Typeableまたは類似した何かに頼ってOKです) Showでこれを行います。

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

Showはレイジーなので、すべてのフィールドを出力しません。あなたはghciにこのコードをruningて、それをテストすることができます。

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

誰もこれでエラーを取得する場合:追加してみてください '{ - #言語DeriveDataTypeable#を - }'ファイルの先頭に。 GHCでは、データと型定義可能関数を派生するときに必要です。 – jPlatte

6

あなたがTypeableを使用しない場合、あなたはまた、次のことができます。

+0

コンストラクタに関係しないカスタムの出力を実装することもできます。 – kqr

+0

'show'は怠惰なので、おそらくそれほど遅くはありません。 'take 5(show(Just undefined))'がうまく動作することに注目してください。 –

+2

'unwords'ではなく' words'を意味します。 (実際、 'takeWhile(/ = '')show)のようなものを書いています。 – Lynn