値コンストラクタのパラメータにクラス制約を定義する方法はありますか?このような値コンストラクタのクラス制約の指定
何か:
data Point2D = (Num a) => Point a a
ようにポイントがある限り、彼らはのNumクラスに所属して任意の引数を取ることができますか?
値コンストラクタのパラメータにクラス制約を定義する方法はありますか?このような値コンストラクタのクラス制約の指定
何か:
data Point2D = (Num a) => Point a a
ようにポイントがある限り、彼らはのNumクラスに所属して任意の引数を取ることができますか?
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コンテキストを回復します。これは基本的には期待していたものです。
しかし、ここで最も重要なのはコンテンツの種類を捨てないことだと思います。そうすることで、基本的にはタイプの操作が不可能になります。
データメンバのインスタンスコンテキストを回復するのは、データ型( 'Point a b ')またはレコードフィールド名' Point {x = a、y = b} ')のパターンマッチングでのみ有効です。しかし、フィールドアクセス機能のためにこれを持つ方法はありますか?つまり、 'Point''pに'(xp) 'のような式でアクセスするときです。 – Lii
はい、ですが、制約の意味は通常のジェネリックタイプとは異なります。
通常、type Foo a = (a, a)
のようにジェネリック医薬品は、すべてのタイプa
ため
を意味し、
Foo a
は2a
の
で構成さしかし、あなたの例では、1が異なり、そのフレーズに必要があります。
som Eタイプ
a
、Point2D
はPoint2D
が
で構成されていることをタイプa
はこのように、一般的なタイプは、ありませんされて2 a
さん
または
で構成されていユニバーサル(すべてのタイプ...)、existential(それはなんらかのタイプです...)。 GHCの下で、我々はこのarticle on the topicで説明したようにextenstion
{-# ExistentialQuantification #-}
を介してこれを許可することができます。あなたのコードは、すべての後に、これはgeneralised algebraic datatypeある
data Point2D = forall a . Num a => Point a a
{-# LANGUAGE GADTs #-}
data Point2D where
Point :: (Num a) => a -> a -> Point2D
です。
確かに!
これは、あなたが欲しいものを行う必要があります。
{-# 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を使用することができますが、あなたはパターンがそれに一致した後のデータで何を行うことはできません。
一般に、タイプ制約は実際に必要な場所に置く方がよいでしょう。これはデータ型ではなく、Num型が必要なメソッドなので、そこで宣言する必要があります。タイプシステムは残りの部分を処理します。 – amccausl