effekt icon indicating copy to clipboard operation
effekt copied to clipboard

Unexpected "effect is not allowed in this context" for a list of first-class functions

Open jiribenes opened this issue 1 year ago • 3 comments

The following program claims that emit[<first-class function type>] is not allowed on the RHS of for, but I can't really tell why:

import stream

def applyAllAndSum(operations: List[(Int) => Unit / emit[Int] at {}], n: Int): Int / {} = sum {
  with val op = for[(Int) => Unit / emit[Int] at {}] { operations.each }
  //                                                   ^^^^^^^^^^^^^^^
  //  Possible overload: stream::each of type [A](List[A]) => Unit / { emit[A] }
  //    Effect emit[Int => Unit / { emit[Int] } at {}] is not allowed in this context.
  (unbox op)(n)
}

Annotating the type of each as operations.each[(Int) => Unit / emit[Int] at {}] doesn't do anything...

For context, the intended application is something like:

def addOne(n: Int) = do emit(n + 1)
def monusOne(n: Int) = if (n > 0) { do emit(n - 1) }

def main() = println(applyAllAndSum([box addOne, box monusOne], 0)) // => 1

jiribenes avatar Dec 07 '24 14:12 jiribenes

I can't even write a "monomorphized" version of for:

def myfor { stream: () => Unit / emit[(Int) => Unit / emit[Int] at {}] } { action: ((Int) => Unit / emit[Int] at {}) => Unit }: Unit / {} =
  try {
    stream()
    // ^
    // Effect emit[Int => Unit / { emit[Int] } at {}] is not allowed in this context.
  } with emit[(Int) => Unit / emit[Int] at {}] { value =>
    resume(action(value))
  }

... is it because of the "nested" effect?

jiribenes avatar Dec 07 '24 14:12 jiribenes

Maybe related to #813 ?

b-studios avatar Feb 04 '25 16:02 b-studios

I think this is the same issue:

interface Bar {}
interface Foo[T] {
  def foo(): T
}

def foo{block: => Unit / Foo[=> Unit / Bar at {}]}: Unit = ()

def main(): Unit / {} = {
  foo {
    val f = do foo[=> Unit / Bar at {}]()
  }
}

It seems to be because of the / Bar effect set. removing it gets rid of the error. Capture sets don't trigger the error. It happens with computation parameters too:

def foo{block: => Unit / Foo[{Bar} => Unit at {}]}: Unit = ()

def main(): Unit / {} = {
  foo {
    val f = do foo[{Bar} => Unit at {}]()
  }
}

kyay10 avatar Oct 21 '25 17:10 kyay10