For the data my app is using, I'm trying to give the data structure (which is a tree) a built-in traversal method, so that the caller can simply call it, providing functions to execute on the branches (Row) and leaves (Container). To allow for the output of any type T, not just a mapping over the tree data, I'm putting the onus on the caller to join the results from calling on subtrees, which they must do explicitly with the descend
callback, which gets passed to the provided rowVisitor
function. My problem is that I'm getting the following error:
Error:(45, 40) missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: T
def descend(node: Content): T = {
^
Here is the code of my data structure and traverse
method:
trait Layout {
def contentTree: Content
def traverse[T](rowVisitor: (Row, Content => T) => T, containerVisitor: Container => T): T = {
def descend(node: Content): T = {
case Row(columns) => rowVisitor(Row(columns), descend)
case Container(name) => containerVisitor(Container(name))
}
descend(contentTree)
}
}
sealed trait Content
case class Row(columns: Seq[Content]) extends Content
case class Container(name: ContainerId) extends Content
Typically, this traverse
function would be called in a template to render this content tree, and therefore T
would be Play's Html
or String
.
Here is the correction, as per the comments:
def traverse[T](rowVisitor: (Row, Content => T) => T)(containerVisitor: Container => T): T = {
def descend(node: Content): T = node match {
case Row(columns) => rowVisitor(Row(columns), descend)
case Container(name) => containerVisitor(Container(name))
}
descend(contentTree)
}
I also split the parameter list so that it can be called like:
layout.traverse[OutputType] { (row, descend) =>
/* call descend on each column of the row, and then aggregate to OutputType */
} { container =>
/* do something with container producing OutputType */
}
It seems to require an explicit type parameter specification or an explicit type on descend
in the first anonymous function to compile. Not sure there's a way around that.