2011-01-26 10 views
9

値コンストラクタのパラメータにクラス制約を定義する方法はありますか?このような値コンストラクタのクラス制約の指定

何か:

data Point2D = (Num a) => Point a a 

ようにポイントがある限り、彼らはのNumクラスに所属して任意の引数を取ることができますか?

+0

一般に、タイプ制約は実際に必要な場所に置く方がよいでしょう。これはデータ型ではなく、Num型が必要なメソッドなので、そこで宣言する必要があります。タイプシステムは残りの部分を処理します。 – amccausl

答えて

11

ExistentialQuantificationまたはGADTsを使用することはできますが、どちらもあなたの望むことを行うことはできません。 2つのPoint2D値を使って算術演算を行うことは決してできません。内容について知っているのは、それらがすべてであり、Numのインスタンスがであるということです。あなたは、コンパイラにそれらに関する他の情報をすべて捨てるように指示しています。これは、特定のペアのPoint2D値に同じ型が含まれている可能性のある情報を破棄するようにコンパイラに指示していることを意味します。その情報がなければ、2つの数値の演算を一度に行うことはできません。Point2D

これはほとんどあなたが望むものではありません。たとえば、distance関数を記述することはできません。そのような限定されたタイプのために、あなたはどのような可能性がありますか?あなたがそれらを使ってできることについては、内容をStringに変換することです。

編集:

私はあなたが何をしようとしていると思います。 Point2Dのすべてが数字であることを確認したいだけです。私はあなたが実際にタイプ消去をしたいとは思わない。

その場合、私は1回の本当に重要な変更で、GADTバージョンでいいと思う:

{-# LANGUAGE GADTs #-} 
data Point2D a where 
    Point :: (Num a) => a -> a -> Point2D a 

これの最終結果はあなただけ同じの2つの値でPointコンストラクタを使用することができるということですNumのインスタンスですが、そのタイプが何かを失うことはありません。さらに、GADTsを使用することにより、Pointコンストラクタのパターンマッチングは、あなたのためにNumコンテキストを回復します。これは基本的には期待していたものです。

しかし、ここで最も重要なのはコンテンツの種類を捨てないことだと思います。そうすることで、基本的にはタイプの操作が不可能になります。

+0

データメンバのインスタンスコンテキストを回復するのは、データ型( 'Point a b ')またはレコードフィールド名' Point {x = a、y = b} ')のパターンマッチングでのみ有効です。しかし、フィールドアクセス機能のためにこれを持つ方法はありますか?つまり、 'Point''pに'(xp) 'のような式でアクセスするときです。 – Lii

4

はい、ですが、制約の意味は通常のジェネリックタイプとは異なります。

通常、type Foo a = (a, a)のようにジェネリック医薬品は、すべてのタイプaため

を意味し、Foo aは2 a

で構成さしかし、あなたの例では、1が異なり、そのフレーズに必要があります。

som EタイプaPoint2DPoint2D

で構成されていることをタイプaはこのように、一般的なタイプは、ありませんされて2 aさん

または

で構成されていユニバーサル(すべてのタイプ...)、existential(それはなんらかのタイプです...)。 GHCの下で、我々はこのarticle on the topicで説明したようにextenstion

{-# ExistentialQuantification #-} 

を介してこれを許可することができます。あなたのコードは、すべての後に、これはgeneralised algebraic datatypeある

data Point2D = forall a . Num a => Point a a 
1
{-# LANGUAGE GADTs #-} 
data Point2D where 
    Point :: (Num a) => a -> a -> Point2D 

です。

2

確かに!

これは、あなたが欲しいものを行う必要があります。

{-# LANGUAGE GADTs #-} 

data Point2D a where 
    Point :: Num a => a -> a -> Point2D a 

p :: Num a => a -> a -> Point2D a 
p = Point 

sumP :: Point2D a -> Point2D a -> a 
sumP (Point a b) (Point c d) = a + b + c + d 

はまたexistensialsを使用することができますが、あなたはパターンがそれに一致した後のデータで何を行うことはできません。

関連する問題