Haskell'de örtük, statik tipte döküm (baskı)


9

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ç:

  1. 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 -> Definitionve 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 ) .
  2. NumTamsayı 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 Numtü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.


1
belki class FromVar ebir yöntemle a kullanabilir fromVar :: Variable -> eveExpression ve Variablesonra değişkenlerin polimorfik türleri x :: FromVar e => evb var olabilir. Şu anda telefonumda beri bu ne kadar iyi çalıştığını test etmedim.
Mor

FromVarTypeclass'ın nasıl yardımcı olacağından emin değilim . Ben tutarken açık yayınları önlemek istiyorsanız Exprbir örneğini Num. Soruyu, elde etmek istediğim gösterime bir örnek ekleyerek düzenledim.
Maciej Bendkowski

Yanıtlar:


8

Alt tiplemeden ziyade polimorfizmden yararlanmak için (Haskell'de sahip olduğunuz tek şey budur), "değişkenin bir ifade olduğunu" düşünmeyin, ancak "hem değişkenlerin hem de ifadelerin ortak bazı işlemleri vardır". Bu işlemler bir tip sınıfına konabilir:

class HasVar e where fromVar :: Variable -> e

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

Sonra, bir şeyleri dökmektense, polimorfik olun. Varsa v :: forall e. HasVar e => e, hem bir ifade hem de bir değişken olarak kullanılabilir.

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

 where

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

Aşağıdaki kodu typecheck yapmak için kullanılan iskelet: https://gist.github.com/Lysxia/da30abac357deb7981412f1faf0d2103

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

İlginç, teşekkürler! Hem değişkenleri hem de ifadeleri varoluşçu türlerin arkasına kısa bir süre için saklamayı düşündüm, ancak ek gösterim getirdiğinden fikri reddettim, bakın V. Başlangıçta istediğim bu değildi, ama belki de reddetmek için çok hızlıydım ... Muhtemelen opaktan kurtulamıyorum V. İlgili bir notta, örneğini nasıl oluşturabilirim V (forall e . HasVar e => e)? Coq'da, endüktif tipte tip hesaplamaları ve örüntü eşleşmesi kullanırdım, ancak Haskell'de bunu nasıl başaracağım belli değil.
Maciej Bendkowski

1
Bir yakalayabilir w :: Variableşekilde ve uygulamak fromVarona: variable = (\w -> V (fromVar w)) <$> (_TODO_ :: Solver Variable).
Li-yao Xia

1
Ve Vimpredicative türleri ile önlenebilir, ancak yine de WIP var olabilir. Ya da variabledolaylı olarak yerine, açıkça bir polimorfik argümanla devam edebiliriz (>>=).
Li-yao Xia
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.