2013-04-09 10 views
6

Aşağıdaki Shift/Reset öğreticisini inceliyorum: http://www.is.ocha.ac.jp/~asai/cw2011tutorial/main-e.pdf.Scala devamlılık eklentisi iç içe kaymayı destekliyor mu?

Şu ana kadar, OchaCaml örneklerini Scala'ya çevirirken oldukça iyi sonuçlar aldım (2.11 numaralı bölüme kadar). Ama şimdi bir duvara çarpmış gibiyim. Bir lambda ifade A-normalleştirmek için

(* a_normal : term_t => term_t *) 
let rec a_normal term = match term with 
    Var (x) -> Var (x) 
    | Lam (x, t) -> Lam (x, reset (fun() -> a_normal t)) 
    | App (t1, t2) -> 
     shift (fun k -> 
     let t = gensym() in (* generate fresh variable *) 
     App (Lam (t, (* let expression *) 
        k (Var (t))), (* continue with new variable *) 
      App (a_normal t1, a_normal t2))) ;; 

işlevi beklenir: - (Bence bu OchaCaml olan) Asai/KISELYOV kağıt kod aşağıdaki özyinelemeli işlevi tanımlar.

// section 2.11 
object ShiftReset extends App { 

    sealed trait Term 
    case class Var(x: String) extends Term 
    case class Lam(x: String, t: Term) extends Term 
    case class App(t1: Term, t2: Term) extends Term 

    val gensym = { 
    var i = 0 
    () => { i += 1; "t" + i } 
    } 

    def a_normal(t: Term): [email protected][Term] = t match { 
    case Var(x) => Var(x) 
    case Lam(x, t) => Lam(x, reset(a_normal(t))) 
    case App(t1, t2) => shift{ (k:Term=>Term) => 
     val t = gensym() 
     val u = Lam(t, k(Var(t))) 
     val v = App(a_normal(t1), a_normal(t2)) 
     App(u, v): Term 
    } 
    } 

} 

aşağıdaki derleme hatası alıyorum: Bu benim Scala çevirisidir Eklenti iç içe shift başa çıkamaz bana anlatıyor düşünüyorum

found : ShiftReset.Term @scala.util.continuations.cpsSynth 
      @scala.util.continuations.cpsParam[ShiftReset.Term,ShiftReset.Term] 
required: ShiftReset.Term 
    case App(t1, t2) => shift{ (k:Term=>Term) => 
              ^
one error found 

... bir yolu var mı kodu derlemek (gözden kaçan temel bir hata mı yoksa bazı geçici çözümler mi)? Desen eşlemesini eğer/else if/else değerine çevirmeyi ve daha fazla yerel değişkenleri tanıtmayı denedim ama aynı hatayı aldım.

Alternatif olarak, ben daha fazla şans Haskell ve Kont monad (+ shift/here reset) kullanarak ya da orada yuvalanmış vardiya ile sınırlama aynı tip olacak olurdu? Haskell etiketini de ekliyorum, çünkü öğreticinin geri kalanından geçmek için Haskell'e geçmem.

Düzenleme: Sürdürme eklentisinin hangi çizgiyle başa çıkamayacağını ve nasıl düzeltileceğini anlayan James'e teşekkürler. (Ben devamı aslında yönetir henüz nasıl kavramak da) kağıt telaffuz edilmesi çıktısını almak

def format(t: Term): String = t match { 
    case Var(x) => s"$x" 
    case Lam(x, t) => s"\\$x.${format(t)}" 
    case App(Lam(x, t1), t2) => s"let $x = ${format(t2)} in ${format(t1)}" 
    case App(Var(x), Var(y)) => s"$x$y" 
    case App(Var(x), t2) => s"$x (${format(t2)})" 
    case App(t1, t2) => s"(${format(t1)}) (${format(t2)})" 
} 

:

sCombinator: 
\x.\y.\z.(xz) (yz) 
reset{a_normal(sCombinator)}: 
\x.\y.\z.let t1 = xz in let t2 = yz in let t3 = t1t2 in t3 

cevap

2

onun cevabını sürümü ve aşağıdaki biçimlendirme kodu kullanarak sorun çizgisidir:

val v = App(a_normal(t1), a_normal(t2)) 

emin değilim ama tip inferencer a_normal birdöndüren gerçeğiyle bocalama düşünüyorum, ama biz bir shift içerisindeyiz, böylece devam aynı şekilde açıklanmamıştır.

Eğer shift bloktan yukarı çizgi çekin eğer derlenir:

: Her iç içe devam uyumlu bir türü varsa genelde iç içe shift s İlişkin

def a_normal(t: Term): [email protected][Term] = t match { 
    case Var(x) => Var(x) 
    case Lam(x, t) => Lam(x, reset(a_normal(t))) 
    case App(t1, t2) => 
    val v = App(a_normal(t1), a_normal(t2)) 
    shift{ (k:Term=>Term) => 
     val t = gensym() 
     val u = Lam(t, k(Var(t))) 
     App(u, v): Term 
    } 
} 

, kesinlikle bunu yapabilirsiniz stdout'a

object NestedShifts extends App { 

    import scala.util.continuations._ 

    def foo(x: Int): [email protected][Unit] = shift { k: (Int => Unit) => 
    k(x) 
    } 

    reset { 
    val x = foo(1) 
    println("x: " + x) 

    val y = foo(2) 
    println("y: " + y) 

    val z = foo(foo(3)) 
    println("z: " + z) 
    } 
} 

Bu program baskılar:

x: 1 
y: 2 
z: 3 
+0

İlginç, koduma geri dönmem gerekecek ve sadece App çıkışı çekip çıkarmayacağımı kontrol etmem gerekiyor. – huynhjl

+0

Teşekkür ederim, şimdi çalışıyor! Şimdi bu zihin bükme kodunun gerçekten ne yaptığını düşünmek zorundayım. – huynhjl