問題
Haskellの次の設計問題を考えてみましょう。変数や一般式(多変量多項式)などを表現したい、シンプルでシンボリックなEDSLがありますx^2 * y + 2*z + 1
。また、私は、表現上の特定のシンボリック方程式を表現言いたいx^2 + 1 = 1
だけでなく、定義のように、x := 2*y - 2
。
目標は次のとおりです。
- 変数と一般式には別のタイプを使用します。特定の関数は、複雑な式ではなく変数に適用される場合があります。たとえば、定義演算子
:=
はタイプである可能性があり(:=) :: Variable -> Expression -> Definition
、左側のパラメーターとして複雑な式を渡すことはできません(明示的なキャストを行わずに、右側のパラメーターとして変数を渡すことができるはずです)。 。 - 式をのインスタンスに
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
ので、:=
変数の定義全体ではなく、左辺の式を与える必要があります。
FromVar
タイプクラスがどのように役立つかわかりません。のExpr
インスタンスを保持しながら、明示的なキャストを避けたいですNum
。達成したい記法の例を追加して質問を編集しました。
class FromVar e
方法とfromVar :: Variable -> e
してのインスタンスを提供Expression
してVariable
、その後、あなたの変数が多型の型を持っているx :: FromVar e => e
など、私は今、自分の携帯電話上だので、私はどれだけこの作品をテストしていません。