LINUX.ORG.RU

Scala, continuations и тип Nothing


0

1

Проблема в следующем: если в блоке shift объявить продолжение, как возвращающее тип Nothing, то компилятор ругается:

error: type mismatch;
 found   : ((Unit) => Nothing) => (Unit) => Nothing
 required: ((Unit) => B) => (Unit) => Nothing

Минимальный пример, демонстрирующий ошибку:

import scala.util.continuations._

object CTest {
    def loop: Nothing = reset {
        shift {c: (Unit => Nothing) => c()}
        loop
    }

   def main(argv: Array[String]) {loop}
}

Однако, если сделать вот так:

import scala.util.continuations._

object CTest {
    def loop: Nothing = reset {
        shift {c: (Unit => Any) => c.asInstanceOf[Unit => Nothing]()}
        loop
    }

   def main(argv: Array[String]) {loop}
}

то всё работает, как и ожидается (т. е. падает от переполнения стека, гг). Кто знает, чем компилятору не нравится тип Nothing в continuation?

★★★

Пару слов о том, зачем мне это надо. Я хочу реализовать асинхронную обработку событий с использованием сопрограмм (coroutines). Т. е. что-то типа такого:

// никогда не вернётся, можно объявить как () => Nothing
def main_loop: Nothing = reset {
    val event = wait_for_event
    shift { cont: (Unit => Nothing)
        // сохранить где-нибудь cont, затем найти обработчик для event
        handle(event)
        cont()
    }
}

def event_handler(event: Event) = {
    val data = next_chunk_of_data(event)
    // обработать данные
}

def next_chunk_of_data(event: Event): Data = reset {
    shift { cont: (Event => Unit)
        if (event.data_available) // данные доступны, извлечь и вернуть
        else {
            // !!!ВАЖНО!!!
            // сохранить cont чтобы при послуплении следующего события
            // handle в main_loop был == cont
            // затем найти сохранённое в main_loop продолжение
            resume_main_loop()
            // Именно для этого продолжение в main_loop
            // Должно возвращать тип Nothing, который является 
            // подтипом для любого типа, т. е. здесь
            // компилятор нас не обматерит за то, что
            // мы пытаемся вернуть что-то другое вместо Data
        }
    }
}
Zenom ★★★
() автор топика

мб поэтому?

trait Nothing
«there exist no instances of this type»

yaws
()

> shift {c: (Unit => Any) => c.asInstanceOf[Unit => Nothing]()}

такой текст показывает, что кто-то не справился со статической типизацией; asInstanceOf если не прямая дыра в системе типов, то перенос проверки в рантайм

вообще так можно скастить что угодно сначала к Unit => Nothing, потом к Unit => ЧеУгодно

у тебя видимо нужно вовсю юзать ко/контравариантость, т.е. сделать что-то похожее на class List[+A], а не пытаться юзать Nothing, который подкласс всем сразу

подробнее не скажу, т.к. со scala.util.continuations не знаком

www_linux_org_ru ★★★★★★
()
Ответ на: комментарий от Zenom

Спасибо, копетаны, мне и так это всё известно. Мне бы узнать, почему сигнатура продолжения не нравится компилятору.

Zenom ★★★
() автор топика
Ответ на: комментарий от Zenom

Что-то я не догоняю, как можно написать ф-цию, которая вернет значение типа Nothing.

val f : Int=>Nothing = (x: Int) => ?;

yaws
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.