Haskellでの暗黙の静的型キャスト(強制)


9

問題

Haskellの次の設計問題を考えてみましょう。変数や一般式(多変量多項式)などを表現したい、シンプルでシンボリックなEDSLがありますx^2 * y + 2*z + 1。また、私は、表現上の特定のシンボリック方程式を表現言いたいx^2 + 1 = 1だけでなく、定義のように、x := 2*y - 2

目標は次のとおりです。

  1. 変数と一般式には別のタイプを使用します。特定の関数は、複雑な式ではなく変数に適用される場合があります。たとえば、定義演算子:=はタイプである可能性があり (:=) :: Variable -> Expression -> Definition、左側のパラメーターとして複雑な式を渡すことはできません(明示的なキャストを行わずに、右側のパラメーターとして変数を渡すことができるはずです)。 。
  2. 式をのインスタンスにNumすることで、整数リテラルを式に昇格させ、補助ラッパー演算子を導入しなくても、加算や乗算などの一般的な代数演算に便利な表記法を使用できます。

言い換えると、変数を式に暗黙的かつ静的に型キャスト(強制)したいのです。そのため、Haskellには暗黙の型キャストがないことを知っています。それにもかかわらず、特定のオブジェクト指向プログラミングの概念(この場合は単純な継承)は、言語拡張の有無にかかわらず、Haskellの型システムで表現できます。軽量の構文を維持しながら、上記の両方の点をどのように満たすことができますか?可能ですか?

討論

ここでの主な問題はNumの型制限であることは明らかです。

(+) :: Num a => a -> a -> a

原則として、変数と式の両方に単一の(一般化された)代数データ型を書き込むことが可能です。次に、:=左側の式が区別され、変数コンストラクターのみが受け入れられ、それ以外の場合はランタイムエラーが発生するように記述できます。ただし、これはクリーンで静的な(つまりコンパイル時の)ソリューションではありません...

理想的には、次のような軽量の構文を実現したいと思います

computation = do
  x <- variable
  t <- variable

  t |:=| x^2 - 1
  solve (t |==| 0)

特に、私のような表記禁止したい t + 1 |:=| x^2 - 1ので、:=変数の定義全体ではなく、左辺の式を与える必要があります。


1
多分あなたは使用することができますclass FromVar e方法とfromVar :: Variable -> eしてのインスタンスを提供ExpressionしてVariable、その後、あなたの変数が多型の型を持っているx :: FromVar e => eなど、私は今、自分の携帯電話上だので、私はどれだけこの作品をテストしていません。
Mor A.

FromVarタイプクラスがどのように役立つかわかりません。のExprインスタンスを保持しながら、明示的なキャストを避けたいですNum。達成したい記法の例を追加して質問を編集しました。
Maciej Bendkowski

回答:


8

サブタイプ化ではなく多態性を活用するには(これはHaskellにあるすべてです)、「変数は式である」とは考えないでください。「変数と式の両方に共通の操作があります」。これらの操作は型クラスに入れることができます:

class HasVar e where fromVar :: Variable -> e

instance HasVar Variable where fromVar = id
instance HasVar Expression where ...

次に、物事をキャストするのではなく、物事をポリモーフィックにします。を持っている場合はv :: forall e. HasVar e => e、式としても変数としても使用できます。

example :: (forall e. HasVar e => e) -> Definition
example v = (v := v)  -- v can be used as both Variable and Expression

 where

  (:=) :: Variable -> Expression -> Definition

以下のコードをタイプチェックするスケルトン:https : //gist.github.com/Lysxia/da30abac357deb7981412f1faf0d2103

computation :: Solver ()
computation = do
  V x <- variable
  V t <- variable
  t |:=| x^2 - 1
  solve (t |==| 0)

興味深い、ありがとう!一時的に存在型の背後に変数と式の両方を非表示にすることを検討しましたが、追加の表記法が導入されたため、アイデアを拒否しましたV。最初はそれが私が欲しかったものではありませんが、おそらく私はそれを却下するのが速すぎたでしょう...おそらく私は不透明を取り除くことができませんV。関連するノートでは、どのようにしてインスタンスを作成できますV (forall e . HasVar e => e)か?Coqでは、型計算と誘導型のパターンマッチングを使用しますが、Haskellでそれを実現する方法は不明です。
Maciej Bendkowski

1
あなたはつかむことができるw :: Variable何とかして適用されfromVar、それに:variable = (\w -> V (fromVar w)) <$> (_TODO_ :: Solver Variable)
Li-yao Xia

1
そしてVimpredicativeタイプで回避、それはまだWIPますすることができます。または、をvariable介して間接的にではなく、明示的にポリモーフィック引数で継続を取ることができ(>>=)ます。
Li-yao Xia
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.