effekt-lang / effekt

A language with lexical effect handlers and lightweight effect polymorphism
https://effekt-lang.org
MIT License
334 stars 24 forks source link

TypeError: $effekt.handleMonadic is not a function #661

Closed omentic closed 3 weeks ago

omentic commented 3 weeks ago

The following code crashes Effekt:

interface Iter {
  def yield(value: Int): Unit
}

def iter(self: List[Int]): Unit / {Iter} =
  self match {
    case Cons(head, tail) => do yield(head); iter(tail)
    case Nil() => ()
  }

def my_map {action: () => Unit / {Iter}} {f: Int => Int}: Unit / {Iter} =
  try action()
  with Iter {
    def yield(value) = do yield(f(value))
  }

def main() =
  try my_map { iter([1, 2, 3]) } { x => x+1 }
  with Iter {
    def yield(x) = println(x)
  }
[apropos@arch effekt]$ java -jar bin/effekt effects/crash.effekt 
/home/apropos/Projects/contrib/effekt/out/crash.js:661
  return $effekt.handleMonadic((p4101) => {
                 ^

TypeError: $effekt.handleMonadic is not a function
    at main_2823 (/home/apropos/Projects/contrib/effekt/out/crash.js:661:18)
    at Object.main (/home/apropos/Projects/contrib/effekt/out/crash.js:685:15)
    at Object.<anonymous> (/home/apropos/Projects/contrib/effekt/out/crash:2:63)
    at Module._compile (node:internal/modules/cjs/loader:1469:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1548:10)
    at Module.load (node:internal/modules/cjs/loader:1288:32)
    at Module._load (node:internal/modules/cjs/loader:1104:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:174:12)
    at node:internal/main/run_main_module:28:49

Node.js v20.18.0
[error] Process exited with non-zero exit code 1.
omentic commented 3 weeks ago

Also, I got this as a result of trying to debug why the following code was erroring:

interface Iter[T] {
  def yield(value: T): Unit
}

def iter[T](self: List[T]): Unit / {Iter[T]} =
  self match {
    case Cons(head, tail) => do yield(head); iter(tail)
    case Nil() => ()
  }

def my_map[T, U] {action: () => Unit / {Iter[T]}} {f: T => U}: Unit / {Iter[U]} =
  try action()
  with Iter[T] {
    def yield(value) = do yield(f(value))
  }

def main() =
  try my_map { iter([1, 2, 3]) } { x => x+1 }
  with Iter[Int] {
    def yield(x) = println(x)
  }
[apropos@arch effekt]$ java -jar bin/effekt effects/zip.effekt 
[error] effects/zip.effekt:19:10: Effects need to be fully known: Iter[T]
        my_map { iter([1, 2, 3]) } { x => x+1 }
         ^^^^^^^^^^^^^^^^^^^

I don't understand this error. What does it mean? I suspect it's representative of some deeper underlying problem with my code, but I don't see why Effekt doesn't know the type Iter[T] here.

b-studios commented 3 weeks ago

The above linked PR addresses the second half of this issue. The problem was that we type check left-to-right, but need to know all effects to subtract them.

In the PR, we now use a simple heuristic to cover your case as this is a common scenario.

For your former problem: can you describe your setup? This error typically occurs if there are two installations of Effekt or an old checkout. The monadic implementation was superseded by a CPS one and should not be used anymore.

omentic commented 3 weeks ago

Ah, apologies! I was coming back to Effekt after a while and pulled down the latest changes, but forgot to rebuild...

The latest compiler (+ adding resume(()) above) works great :smiley: