2016-07-02 6 views
0

データ型のコンストラクタ "タグ"を比較したいと思います。コンストラクタの選択時にデータ型の値を比較するだけ

これを行う簡単な方法はありますか?

data D = A | B Int | C String 
check k d = ? 

check A (A) -- True 
check B (B 55) -- True 
check C (C "xxx") -- True 
+0

は自問:: 'どのタイプを持っているcheck'う期待どおりに動作

{-# LANGUAGE DeriveDataTypeable #-} import Data.Typeable data D = A | B Int | C String deriving Typeable check :: Typeable a => a -> D -> Bool check p d = typeOf p == conTypeRep where conTypeRep = case d of A -> typeOf A B {} -> typeOf B C {} -> typeOf C 

?最初の引数は 'D'型の値か' Int - > D'型の関数か 'String-> D'型の関数です。これらの3つを統一して...統一することはできません。そうすることはできません。しかし、あなたは 'check 'のようなことをすることができます。コンストラクタの名前にマッチする" A = True "パターン... – Bakuriu

答えて

4

おそらくコンストラクタとワイルドカードのパターンを一致させたいと思うでしょう。そう:

check :: D -> D -> Bool 
check A A = True 
check (B _) (B _) = True 
check (C _) (C _) = True 
check _ _ = False 
+1

これはレコード構文で特にうまくいきます:' check A = True; B {} =真であることを確認する。 ... '。フィールドの空白をすべて記入する必要はありません。 – dfeuer

2

これを行うにはいくつかの方法がありますが、どれも完璧ではありません。あなたは、データの種別型担当者を比較することによって、似たような行うことができます

{-# LANGUAGE KindSignatures #-} 
{-# LANGUAGE DataKinds #-} 
{-# LANGUAGE TypeApplications #-} 
import Data.Typeable 

data D = A | B Int | C Char 

kCheck :: Typeable a => Proxy (a::k) -> D -> Bool 
kCheck p d = typeRep p == kTypeRep where 
    kTypeRep = case d of 
    A -> typeRep (Proxy @ 'A) 
    B {} -> typeRep (Proxy @ 'B) 
    C {} -> typeRep (Proxy @ 'C) 

を(あなたはGHC 8.0.1がTypeApplicationsを削除し、:: Proxy 'A@ 'Aを置き換えていない場合)私は(これはGHC 7.10を必要だと思いますまたはで7.8)。

kCheck (Proxy @ 'B) (B 3) 
True 
kCheck (Proxy @ 'C) A 
False 

それとも、TemplateHaskellを使用してName秒比較することができます:あなたは幸せな文字列を比較している場合は、自動的にDataからtoConstrを使用してそれらを導くことができる

{-# LANGUAGE TemplateHaskell #-} 
import Language.Haskell.TH 

data D = A | B Int | C Char 

thCheck :: Name -> D -> Bool 
thCheck n d = n == conName 
    where 
    conName = case d of 
     A -> 'A 
     B {} -> 'B 
     C {} -> 'C 

> thCheck 'B (B 3) 
True 
> thCheck 'A (C 'a') 
False 

を:

{-# LANGUAGE DeriveDataTypeable #-} 

import Data.Data 

data D = A | B Int | C Int 
    deriving Data 

dCheck :: String -> D -> Bool 
dCheck s d = s == show (toConstr d) 

あなたが望むものに最も近い方法がありますが、これは各タイプのコンストラクターに固有のタイプがある場合にのみ機能します。 したがってABのタイプ担当者は両方ともInt -> Dとなるため、これはdata D = A Int | B Intでは機能しません。

> check B (B 3) 
True 
> check C A 
False 
関連する問題