2017-11-27 18 views
2

私は特定のデータコンストラクタを別のデータコンストラクタの内部に入れることはできませんが、両方とも同じ型を与えることはできますか?

[Leaf 1, Rooted (Leaf 2), Branch (Leaf 3) (Branch (Leaf 4) (Leaf 5))] 

なく

[Leaf 1, Rooted (Leaf 2), Branch (Rooted (Leaf 3)) (Branch (Leaf 4) (Leaf 5))] 

すなわちすることができますHaskellではタイプTをしたいのですが。 Rootedを除くTのすべてのコンストラクタは、Branchの最初の引数または2番目の引数に現れることがあります(完全なコードにはさらにいくつかのコンストラクタがあります)。

私たちはBranch (Rooted …) …を行うことはできません保証しますが、またそれは、異なる種類([T True, T False])のリストになりますので、我々は[Rooted …, One …]を行うことができないことを意味

{-# LANGUAGE GADTs #-} 
data T (x::Bool) where 
    Leaf :: Int -> T True 
    Rooted :: T True -> T False 
    Branch :: T True -> T True -> T True 

のようなものを試してみました。

私は

{-# LANGUAGE GADTs, DataKinds, KindSignatures #-} 
data T where 
    Leaf :: Int -> T 
    Rooted :: T -> T 
    Branch :: UnRooted a => a -> a -> T 
class UnRooted a 
instance UnRooted Leaf 
instance UnRooted Branch 

を行うことができます願って、DataKindsに見えたが、その後、GHC(7.10.3)はData constructor ‘Leaf’ comes from an un-promotable type ‘T’を与えます。

ハスケルでこれを行う方法はありますか?あなたはブール値を隠し、コンストラクタ内のすべてを包む場合

+1

同じ(同種の)リストに入れる場合は、同じタイプをルートと非ルートに付ける必要があります。しかし、同じ型を持つ場合は、他のものをサブツリーに置き換えることができます。このように、これは不可能です。おそらく、あなたの最初の試みを実体ラッパーにラップして、その型のブール値を取り除くことは可能でしょうか?または合計型を使用しますか?または、GADTを使用せずに、ルートを独自の型にします(まだ和またはラッパーを使用します)。 – chi

+2

あなたはこれを望む理由を説明できますか?つまり、 'Rooted'コンストラクタは何のためにあるのでしょうか? – MathematicalOrchid

+0

パターンマッチャーです。私はかなりコンパクトな構文で簡単なリストとして式を書くことができるようにしたいと思います。 'Branch'は実際には2つの式を結合する演算子のセットです。 'Rooted'は"このパターンが前/次のパターンのすぐ隣に現れる必要はありません "といったようなラッパーです。しかし、この種のタイプをクリーン/シンプルな方法で定義するのは難しいようです。だから私は別のアプローチを見つけるべきだと思います。 – unhammer

答えて

3

あなたは最初のソリューションを使用することができます。私たちはとにかく種類をラップする必要があるとしている場合

{-# LANGUAGE GADTs, DataKinds, KindSignatures, RankNTypes #-} 
data T (x::Bool) where 
    Leaf :: Int -> T True 
    Rooted :: T True -> T False 
    Branch :: T True -> T True -> T True 

data TWrap = forall (x :: Bool). TWrap (T x) 

[TWrap $ Leaf 1, TWrap $ Rooted (Leaf 2), TWrap $ Branch (Leaf 3) (Branch (Leaf 4) (Leaf 5))] 

はしかし、それだけで行くことはおそらく良いでしょう

data T = Leaf Int | Branch T T 
data TWrap = Unrooted T | Rooted T 

[Unrooted $ Leaf 1, Rooted $ Leaf 2, Unrooted $ Branch (Leaf 3) (Branch (Leaf 4) (Leaf 5))] 

が何を求めていることは基本的にdependent typesで、Haskellはありません(012:タイプを分割するのがより簡単な解決のために)。

+0

従属型に関する私のコメントが不正確なら、私に修正してください。 Haskellは従属型(GADTなど)のサポートをいくつか行っていますが、質問に記載されている説明を満たすためには、より多くのサポートが必要と考えられます。 – Hjulle

関連する問題