1

したがって、次のようなことができれば便利です(必ずしもこの形式ではなく、一般的な考え方です)。

data Sub = SubA | SubB
data Super = Sub | SuperB

isSub :: Super -> Bool
isSub Sub = True
isSub _ = False

したがって、isSub SubAは(エラーではなく)Trueを報告します。現時点では、次のようなことを行う可能性があります。

data Super = SubA | SubB | SuperB

isSub :: Super -> Bool
isSub SubA = True
isSub SubB = True
isSub _ = False

それはひどいことでも何でもありませんが、うまく拡張せず(SubZまでの場合はSubのようにこれはひどく不格好です)、Sub型を独自の型クラスに追加することはできません。この問題を回避するには、Subをラップします。

data Sub = SubA | SubB
data Super = SuperA Sub | SuperB

isSub :: Super -> Bool
isSub (SuperA _) = True
isSub _ = False

しかし今、あなたは彼らをスーパーとして使うためにあなたの潜水艦を包むことを確実にしなければなりません...再びひどいことではありません。私が望むセマンティクスを実際にはうまく表現していません(つまり、Superは任意のSubまたはSuperBにすることができます)。最初の(合法的な)例は「Supercan be SubA ...」であり、2番目の例は「Supercan be SuperA that take aSub...」です。

EDTI:音楽との混同を避けるためにいくつかの名前を変更します。

PS技術的には、これはHaskellでSchemeの数値タワーを表現する方法を考えていたときに始まりました...しかし、「Type1はType2に加えてx、y、... )。

4

3 に答える 3

1

ひどいことでも何でもありませんが、うまく拡張しません

テンプレートHaskellを使用した場合は問題ありません。deriveガイダンスとしてツールのmakeIsルーチンを見ていきます。

しかし今、あなたはそれらをスーパーとして使用するためにあなたの潜水艦をラップすることを確認する必要があります

いいえ、型システムは忘れた場合に教えてくれます。たとえば、

data Super = Sub Sub | Super
data Sub = SubA | SubB

Sub次に、を使用しているが、を期待しているコンテキストSuperがキャッチされます。すでにご存知だと思いますが、何か別の意味ですか?

于 2012-12-17T06:43:28.190 に答える
0

あなたはのようなものを持つことはできません

data Sub = SubA | SubB
data Super = Sub | SuperB

上記の構文が許可されているとすると、問題には、その型がであるか。SubAであるかがわからない値コンストラクターが与えられます。そのため、型をコンストラクターでラップする必要があります。SubSuper

2番目の例では、現在の方法がデフォルトの方法である必要がありますが、showの使用は非常に遅いため、これを行うことはお勧めしませんが、ハックして簡単にすることができます。これに似た他のハックを試すことができます。

import Data.List
data Super = SubA | SubB | SuperB deriving Show
isSub :: Super -> Bool
isSub m = isPrefixOf "Sub" (show m)

上記のようなものが本当に必要な場合は、あなたが行ったように関数を定義することをお勧めします。THを使用すると、時間を節約できる可能性があります。

あなたの3番目のケースは、私が本当にお勧めすることです。SuperA私が上で言った理由のために、あなたはのようなラッパーコンストラクターを持っている必要があります。そのため、type1をtype2にx、y、zを加えたものにすることはできません。最も近いのは、コンストラクターで要素をラップするか、型クラスを使用することです。

data Sub = SubA | SubB
data Sup = SuperA | SuperB

class Super a where
  isSub :: a -> Bool
  isSub _ = True

instance Super Sup where
    isSub _ = False

instance Super Sub

data SupSup = SuperSuperA | SuperSuperB

class SuperSuper a where
    isSuper :: a -> Bool
    isSuper _ = True


instance SuperSuper SupSup where
    isSuper _ = False

instance SuperSuper Sup
instance SuperSuper Sub

Superここ(型クラスであり、型ではない)にはSub、余分な( )が含まれていると考えることができますSup

于 2012-12-17T06:45:47.257 に答える
0

Data.DataおよびData.Typleableのインスタンスでlens(Control.Lens)ライブラリを使用することを検討することをお勧めします。Lensは、リスト、タプル、およびその他すべてのデータ型におけるこれらのタイプのマルチレベルの問題を解決する試みです。

>data Sub =  SubA | SubB deriving (Show, Data, Typeable, Eq)
>data Super =  SuperA Sub | SuperB deriving (Show, Data, Typeable, Eq)

-- A little bit of a hack, there is probably a better way of doing this
>isSub' :: Sub -> Bool
>isSub' x = typeOf x == typeOf SubA

>tmp1 = SuperA SubA
>tmp2 = SuperA SubB

>isSub x = anyOf biplate (isSub') x

>isSub tmp1
True
>issub tmp2
True

isSubは実際にはあまりにも一般的であり、提供されたデータ型の子のいずれかがSub型であるかどうかを確認します。したがって、ツリーがあり、ツリー内にサブがあった場合、それはTrueになります。ただし、これをユースケースのみに制限することは可能です。

Lensライブラリの利点は、タイプ階層に別のレイヤーを追加できることです。

>data SuperSuper =  SuperSuperA Super | SuperSuperB | SuperSuperC Sub deriving (Show,Data,Typeable)

>tmp3 = SuperSuperA (SuperA SubA)
>tmp4 = SuperSuperC SubB

>isSub tmp3
True
>isSub tmp4
True
于 2013-01-03T01:40:48.473 に答える