Как определить тип: бесконечная функция? - PullRequest
4 голосов
/ 17 июня 2019

Как определить тип InfiniteFunction, который является функцией и при вызове возвращает другой InfiniteFunction

Тип выглядит так:

() => () => () => ... // infinite

или рекурсивный:

type InfiniteFunction = () => InfiniteFunction

И это не работает

scala> type InfiniteFunction = () => InfiniteFunction
<console>:11: error: illegal cyclic reference involving type InfiniteFunction
       type InfiniteFunction = () => InfiniteFunction

Задача

Я хочу сделать преобразование cps для этой функции:

def travel(tree: TreeNode): Unit = {
  if (tree != null) {
    travel(tree.left)
    println(tree.value)
    travel(tree.right)
  }
}

после cps:

def r[T](f: => T): () => T = () => f
def travel(tree: TreeNode, cb: () => AnyRef): Unit = {
  if (tree != null) {
    travel(tree.left, r{
      println(tree.value)
      travel(tree.right, cb)
    })
  } else {
    cb()
  }
}

Затем я хочу оптимизировать хвостовой вызов, выдавая их, вместо этого вызывая их:

def r[T](f: => T): () => T = () => f
def travel(tree: TreeNode, cb: () => InfiniteFunction): InfiniteFunction = {
  if (tree != null) {
    r(travel(tree.left, r{
      println(tree.value)
      r(travel(tree.right, cb))
    }))
  } else {
    r(cb())
  }
}

// demonstration how to use travel
var f: InfiniteFunction = r(
  travel(tree, r(throw new RuntimeException("it is over")))
)
// this will end by the exception "it is over"
while (true) f = f()

Здесь требуется тип InfiniteFunction, без типа InfiniteFunction, требуется преобразование типа:

def r[T](f: => T): () => T = () => f
def travel(tree: TreeNode, cb: () => AnyRef): () => AnyRef = {
  if (tree != null) {
    r(travel(tree.left, r {
      println(tree.value)
      r(travel(tree.right, cb))
    }))
  } else {
    r(cb())
  }
}

var f: () => AnyRef = r(
  travel(tree, r(throw new RuntimeException("it is over")))
)
while (true) f = f().asInstanceOf[() => AnyRef]

1 Ответ

6 голосов
/ 17 июня 2019

Используйте черту вместо псевдонима типа для решения проблемы с циклической ссылкой:

trait Inf extends (Unit => Inf)

Также Unit является типом ()

...