Sorun
Haskell'de aşağıdaki tasarım sorununu düşünün. Değişkenleri ve genel ifadeleri (çok değişkenli polinomlar) ifade etmek istediğim basit, sembolik bir EDSL var x^2 * y + 2*z + 1
. Buna ek olarak, ben ifadeler, diyelim üzerinde belirli sembolik denklemler ifade etmek istiyorum x^2 + 1 = 1
, hem de tanımları gibi x := 2*y - 2
.
Amaç:
- Değişkenler ve genel ifadeler için ayrı bir türü vardır - bazı işlevler karmaşık ifadelere değil değişkenlere uygulanabilir. Örneğin, bir tanım operatörü
:=
tipte olabilir(:=) :: Variable -> Expression -> Definition
ve karmaşık bir ifadeyi sol taraf parametresi olarak iletmek mümkün olmamalıdır (ancak bir değişkeni sağ taraf parametresi olarak, açık döküm olmadan geçirmek mümkün olmalıdır ) . Num
Tamsayı değişmez değerlerini ifadelere yükseltmek ve bazı yardımcı sarmalayıcı işleçleri eklemeden toplama veya çarpma gibi yaygın cebirsel işlemler için uygun bir gösterim kullanmak için ifadelerin bir örneğini alın .
Başka bir deyişle, değişkenlerin ifadelere örtülü ve statik bir tür dökümü (zorlama) almak istiyorum. Şimdi biliyorum ki Haskell'de örtük tipte dökümler yok. Bununla birlikte, bazı nesne yönelimli programlama kavramları (bu durumda basit kalıtım,) olan expressible ile veya dil uzantıları olmadan ya Haskell'ın tip sisteminde. Hafif bir sözdizimini korurken yukarıdaki her iki noktayı da nasıl tatmin edebilirim? Hatta mümkün mü?
Tartışma
Buradaki ana sorunun Num
tür kısıtlaması olduğu açıktır , ör.
(+) :: Num a => a -> a -> a
Prensip olarak, hem değişkenler hem de ifadeler için tek (genelleştirilmiş) bir cebirsel veri türü yazmak mümkündür. Daha sonra, :=
öyle bir şekilde yazılabilir ki, sol taraftaki ifade ayırt edilir ve yalnızca değişken bir kurucu kabul edilir, aksi takdirde çalışma zamanı hatası oluşur. Ancak bu temiz, statik (yani derleme zamanı) bir çözüm değildir ...
Misal
İdeal olarak, hafif bir sözdizimi elde etmek istiyorum.
computation = do
x <- variable
t <- variable
t |:=| x^2 - 1
solve (t |==| 0)
Özellikle, gösterimi yasaklamak istiyorum,
t + 1 |:=| x^2 - 1
çünkü :=
bir sol tanımın tamamını değil, bir değişkenin tanımını vermelidir.
FromVar
Typeclass'ın nasıl yardımcı olacağından emin değilim . Ben tutarken açık yayınları önlemek istiyorsanız Expr
bir örneğini Num
. Soruyu, elde etmek istediğim gösterime bir örnek ekleyerek düzenledim.
class FromVar e
bir yöntemle a kullanabilirfromVar :: Variable -> e
veExpression
veVariable
sonra değişkenlerin polimorfik türlerix :: FromVar e => e
vb var olabilir. Şu anda telefonumda beri bu ne kadar iyi çalıştığını test etmedim.