2017-12-05 18 views
0

にマッチしますは、どのように私が持っているようなタイプ

infixr 9 ||| 
data a ||| b = A a|B b deriving (Eq, Data, Show) 

class IsTag a where 
    anyTag :: a 

と私は例えば、IsTagのインスタンスであるこのa|||bいくつかの値に保つ:A (B (A x)) - ネストの深いは任意のものとすることができる、確認してください。そして、xanyTagと等しいことを検出する関数を書きたいので、a|||bを返し、Bool - xのインスタンスのanyTagに等しい基本値(この例ではx)を返します。どのようにそのような関数を書く? 「無限型」などのエラーでパターンマッチングを行うことができません。deriving Dataa|||bに追加し、xの型にDataのものを使用することを希望していますが、わかりませんそのような再帰型を介して倍/トラバースする。

+3

書き込みできるコードの種類の最小限の完全な例を追加できますか?あなたが解決しようとしている実際の問題を説明するのに役立ちます。 –

+0

[旅の始まり](https://stackoverflow.com/questions/47577470/read-of-types-sum)これは、一般的なread/match/showを持つさまざまな種類のタグを組み合わせたものです。すべてが良いですし、課題は解決しましたが、私は[tag1、tag2]や[tag1、anyTag](これは擬似コード)のようなタグにマッチするケースを区別する必要があります。場合)。ですから、タグタイプ( 'a ||| b')が' == anyTag'であるものを保持していることを確認する必要があります –

答えて

2

それはこれよりはるかに良く得ることはありません。ここでの主な欠点は、これはあなたがテストしているにもかかわらず、|||の両側のタイプはIsAnyTagインスタンスされなければならないことを必要とすることである

{-# LANGUAGE DefaultSignatures #-} 
class IsAnyTag a where 
    isAnyTag :: a -> Bool 
    default isAnyTag :: (Eq a, IsTag a) => a -> Bool 
    isAnyTag = (anyTag ==) 

instance (IsAnyTag a, IsAnyTag b) => IsAnyTag (a ||| b) where 
    isAnyTag (A a) = isAnyTag a 
    isAnyTag (B b) = isAnyTag b 

-- and one more line of `instance IsAnyTag X` for each `X` that 
-- is an instance of `IsTag` 

片側のみ。それらは静的な型チェックのブレークです。

関連する問題