How to read input from a file and convert data lines of the file to List[Map[Int,String]] using scala? - scala

My Query is, read input from a file and convert data lines of the file to List[Map[Int,String]] using scala. Here I give a dataset as the input. My code is,
def id3(attrs: Attributes,
examples: List[Example],
label: Symbol
) : Node = {
level = level+1
// if all the examples have the same label, return a new node with that label
if(examples.forall( x => x(label) == examples(0)(label))){
new Leaf(examples(0)(label))
} else {
for(a <- attrs.keySet-label){ //except label, take all attrs
("Information gain for %s is %f".format(a,
informationGain(a,attrs,examples,label)))
}
// find the best splitting attribute - this is an argmax on a function over the list
var bestAttr:Symbol = argmax(attrs.keySet-label, (x:Symbol) =>
informationGain(x,attrs,examples,label))
// now we produce a new branch, which splits on that node, and recurse down the nodes.
var branch = new Branch(bestAttr)
for(v <- attrs(bestAttr)){
val subset = examples.filter(x=> x(bestAttr)==v)
if(subset.size == 0){
// println(levstr+"Tiny subset!")
// zero subset, we replace with a leaf labelled with the most common label in
// the examples
val m = examples.map(_(label))
val mostCommonLabel = m.toSet.map((x:Symbol) => (x,m.count(_==x))).maxBy(_._2)._1
branch.add(v,new Leaf(mostCommonLabel))
}
else {
// println(levstr+"Branch on %s=%s!".format(bestAttr,v))
branch.add(v,id3(attrs,subset,label))
}
}
level = level-1
branch
}
}
}
object samplet {
def main(args: Array[String]){
var attrs: sample.Attributes = Map()
attrs += ('0 -> Set('abc,'nbv,'zxc))
attrs += ('1 -> Set('def,'ftr,'tyh))
attrs += ('2 -> Set('ghi,'azxc))
attrs += ('3 -> Set('jkl,'fds))
attrs += ('4 -> Set('mno,'nbh))
val examples: List[sample.Example] = List(
Map(
'0 -> 'abc,
'1 -> 'def,
'2 -> 'ghi,
'3 'jkl,
'4 -> 'mno
),
........................
)
// obviously we can't use the label as an attribute, that would be silly!
val label = 'play
println(sample.try(attrs,examples,label).getStr(0))
}
}
But How I change this code to - accepting input from a .csv file?

I suggest you use Java's io / nio standard library to read your CSV file. I think there is no relevant drawback in doing so.
But the first question we need to answer is where to read the file in the code? The parsed input seems to replace the value of examples. This fact also hints us what type the parsed CSV input must have, namely List[Map[Symbol, Symbol]]. So let us declare a new class
class InputFromCsvLoader(charset: Charset = Charset.defaultCharset()) {
def getInput(file: Path): List[Map[Symbol, Symbol]] = ???
}
Note that the Charset is only needed if we must distinguish between differently encoded CSV-files.
Okay, so how do we implement the method? It should do the following:
Create an appropriate input reader
Read all lines
Split each line at the comma-separator
Transform each substring into the symbol it represents
Build a map from from the list of symbols, using the attributes as key
Create and return the list of maps
Or expressed in code:
class InputFromCsvLoader(charset: Charset = Charset.defaultCharset()) {
val Attributes = List('outlook, 'temperature, 'humidity, 'wind, 'play)
val Separator = ","
/** Get the desired input from the CSV file. Does not perform any checks, i.e., there are no guarantees on what happens if the input is malformed. */
def getInput(file: Path): List[Map[Symbol, Symbol]] = {
val reader = Files.newBufferedReader(file, charset)
/* Read the whole file and discard the first line */
inputWithHeader(reader).tail
}
/** Reads all lines in the CSV file using [[java.io.BufferedReader]] There are many ways to do this and this is probably not the prettiest. */
private def inputWithHeader(reader: BufferedReader): List[Map[Symbol, Symbol]] = {
(JavaConversions.asScalaIterator(reader.lines().iterator()) foldLeft Nil.asInstanceOf[List[Map[Symbol, Symbol]]]){
(accumulator, nextLine) =>
parseLine(nextLine) :: accumulator
}.reverse
}
/** Parse an entry. Does not verify the input: If there are less attributes than columns or vice versa, zip creates a list of the size of the shorter list */
private def parseLine(line: String): Map[Symbol, Symbol] = (Attributes zip (line split Separator map parseSymbol)).toMap
/** Create a symbol from a String... we could also check whether the string represents a valid symbol */
private def parseSymbol(symbolAsString: String): Symbol = Symbol(symbolAsString)
}
Caveat: Expecting only valid input, we are certain that the individual symbol representations do not contain the comma-separation character. If this cannot be assumed, then the code as is would fail to split certain valid input strings.
To use this new code, we could change the main-method as follows:
def main(args: Array[String]){
val csvInputFile: Option[Path] = args.headOption map (p => Paths get p)
val examples = (csvInputFile map new InputFromCsvLoader().getInput).getOrElse(exampleInput)
// ... your code
Here, examples uses the value exampleInput, which is the current, hardcoded value of examples if no input argument is specified.
Important: In the code, all error handling has been omitted for convenience. In most cases, errors can occur when reading from files and user input must be considered invalid, so sadly, error handling at the boundaries of your program is usally not optional.
Side-notes:
Try not to use null in your code. Returning Option[T] is a better option than returning null, because it makes "nullness" explicit and provides static safety thanks to the type-system.
The return-keyword is not required in Scala, as the last value of a method is always returned. You can still use the keyword if you find the code more readable or if you want to break in the middle of your method (which is usually a bad idea).
Prefer val over var, because immutable values are much easier to understand than mutable values.
The code will fail with the provided CSV string, because it contains the symbols TRUE and FALSE which are not legal according to your programs logic (they should be true and false instead).
Add all information to your error-messages. Your error message only tells me what that a value for the attribute 'wind is bad, but it does not tell me what the actual value is.

Read a csv file ,
val datalines = Source.fromFile(filepath).getLines()
So this datalines contains all the lines from the csv file.
Next, convert each line into a Map[Int,String]
val datamap = datalines.map{ line =>
line.split(",").zipWithIndex.map{ case (word, idx) => idx -> word}.toMap
}
Here, we split each line with ",". Then construct a map with key as column number and value as each word after the split.
Next, If we want List[Map[Int,String]],
val datamap = datalines.map{ line =>
line.split(",").zipWithIndex.map{ case (word, idx) => idx -> word}.toMap
}.toList

Related

In a scala macro, how to get the full name that a class will have at runtime?

The intention is to get at run-time some info of particular classes that is available only at compile-time.
My approach was to generate the info at compile time with a macro that expands to a map that contains the info indexed by the runtime class name.
Something like this:
object macros {
def subClassesOf[T]: Map[String, Info] = macro subClassesOfImpl[T];
def subClassesOfImpl[T: ctx.WeakTypeTag](ctx: blackbox.Context): ctx.Expr[Map[String, Info]] = {
import ctx.universe._
val classSymbol = ctx.weakTypeTag[T].tpe.typeSymbol.asClass
val addEntry_codeLines: List[Tree] =
for {baseClassSymbol <- classSymbol.knownDirectSubclasses.toList} yield {
val key = baseClassSymbol.asType.toType.erasure.typeSymbol.fullName
q"""builder.addOne($key -> new Info("some info"));"""
}
q"""
val builder = Map.newBuilder[String, Info];
{..$addEntry_codeLines}
builder.result();""";
ctx.Expr[Map[String, Info]](body_code);
}
}
Which would we used like this:
object shapes {
trait Shape;
case class Box(h: Int, w: Int);
case class Sphere(r: Int);
}
val infoMap = subclassesOf[shapes.Shape];
val box = Box(3, 7);
val infoOfBox = infoMap.get(box.getClass.getName)
The problem is that the names of the erased classes given by that macro are slightly different from the ones obtained at runtime by the someInstance.getClass.getName method. The first uses dots to separate container from members, and the second uses dollars.
scala> infoMap.mkString("\n")
val res7: String =
shapes.Box -> Info(some info)
shapes.Sphere -> Info(some info)
scala> box.getClass.getName
val res8: String = shapes$Box
How is the correct way to obtain at compile time the name that a class will have at runtime?
Vice versa, at runtime, having Java name of a class (with dollars) you can obtain Scala name (with dots).
box.getClass.getName
// com.example.App$shapes$Box
import scala.reflect.runtime
val runtimeMirror = runtime.currentMirror
runtimeMirror.classSymbol(box.getClass).fullName // com.example.App.shapes.Box
This can be done even with replace
val nameWithDot = box.getClass.getName.replace('$', '.')
if (nameWithDot.endsWith(".")) nameWithDot.init else nameWithDot
// com.example.App.shapes.Box
Anyway, at compile time you can try
def javaName[T]: String = macro javaNameImpl[T]
def javaNameImpl[T: ctx.WeakTypeTag](ctx: blackbox.Context): ctx.Expr[String] = {
import ctx.universe._
val symbol = weakTypeOf[T].typeSymbol
val owners = Seq.unfold(symbol)(symb =>
if (symb != ctx.mirror.RootClass) Some((symb, symb.owner)) else None
)
val nameWithDollar = owners.foldRight("")((symb, str) => {
val sep = if (symb.isPackage) "." else "$"
s"$str${symb.name}$sep"
})
val name = if (symbol.isModuleClass) nameWithDollar else nameWithDollar.init
ctx.Expr[String](q"${name: String}")
}
javaName[shapes.Shape] // com.example.App$shapes$Shape
One more option is to use runtime reflection inside a macro. Replace
val key = baseClassSymbol.asType.toType.erasure.typeSymbol.fullName
with
val key = javaName(baseClassSymbol.asType.toType.erasure.typeSymbol.asClass)
where
def subClassesOfImpl[T: ctx.WeakTypeTag](ctx: blackbox.Context): ctx.Expr[Map[String, Info]] = {
import ctx.universe._
def javaName(symb: ClassSymbol): String = {
val rm = scala.reflect.runtime.currentMirror
rm.runtimeClass(symb.asInstanceOf[scala.reflect.runtime.universe.ClassSymbol]).getName
}
...
}
This works only with classes existing at compile time. So the project should be organized as follows
subproject common. Shape, Box, Sphere
subproject macros (depends on common). def subClassesOf...
subproject core (depends on macros and common). subclassesOf[shapes.Shape]...
The answer from #Dmytro_Mitin helped me to notice that the scala reflect API does not offer a fast one line method to get the name that a class will have at runtime, and guided me solve my particular problem in another way.
If what you need to know is not the run-time class name itself but only if it matches the name accesible at compile-time, efficiently, then this answer may be useful.
Instead of figuring out what the name will be at runtime, which is apparently not possible before knowing all the classes; just find out if the name we know at compile time corresponds or not to one obtained at runtime.
This can be achieved with a string comparator that considers the relevant character and ignores whatever the compiler appends later.
/** Compares two class names based on the length and, if both have the same length, by alphabetic order of the reversed names.
* If the second name (`b`) ends with a dollar, or a dollar followed by digits, they are removed before the comparison begins. This is necessary because the runtime class name of: module classes have an extra dollar at the end, local classes have a dollar followed by digits, and local object digits surrounded by dollars.
* Differences between dots and dollars are ignored if the dot is in the first name (`a`) and the dollar in the second name (`b`). This is necessary because the runtime class name of nested classes use a dollar instead of a dot to separate the container from members.
* The names are considered equal if the fragments after the last dot of the second name (`b`) are equal. */
val productNameComparator: Comparator[String] = { (a, b) =>
val aLength = a.length;
var bLength = b.length;
var bChar: Char = 0;
var index: Int = 0;
// Ignore the last segment of `b` if it matches "(\$\d*)+". This is necessary because the runtime class name of: module classes have an extra dollar at the end, local classes have a dollar followed by a number, and local object have a number surrounded by dollars.
// Optimized versiĆ³n
var continue = false;
do {
index = bLength - 1;
continue = false;
// find the index of the last non digit character
while ( {bChar = b.charAt(index); Character.isDigit(bChar)}) {
index -= 1;
}
// if the index of the last non digit character is a dollar, remove it along with the succeeding digits for the comparison.
if (b.charAt(index) == '$') {
bLength = index;
// if something was removed, repeat the process again to support combinations of edge cases. It is not necessary to know all the edge cases if it's known that any dollar or dollar followed by digits at the end are not part of the original class name. So we can remove combinations of them without fear.
continue = true;
}
} while(continue)
// here starts the comparison
var diff = aLength - bLength;
if (diff == 0 && aLength > 0) {
index = aLength - 1;
do {
val aChar = a.charAt(index);
bChar = b.charAt(index);
diff = if (aChar == '.' && bChar == '$') {
0 // Ignore difference between dots and dollars. This assumes that the first name (an) is obtained by the macro, and the second (bn) may be obtained at runtime from the Class object.
} else {
aChar - bChar;
}
index -= 1;
} while (diff == 0 && index >= 0 && bChar != '.')
}
diff
}
Note that it is designed to compare names of classes that extend the same sealed trait or abstract class. Which means that the names may differ only after the last dot.
Also note that the first argument only supports a compile time name (only dots), while the second supports both, a compile-time or a run-time name.

Spark: Transforming JSON files to correct format

I've 100+ million records stored in files with the following JSON structure (real data has way more columns, rows and is also nested)
{"id":"2-2-3","key":"value"}{"id":"2-2-3","key":"value"}{"id":"2-2-3","key":"value"}{"id":"2-2-3","key":"value"}{"id":"2-2-3","key":"value"}
The sqlContext.read.json function is unable to parse this since the records aren't on multiple lines but on one big line. The solution below solves this problem, but is a big performance killer. What would be the best way, performance wise, to handle this issue in Apache Spark?
val rdd = sc.wholeTextFiles("s3://some-bucket/**/*")
val validJSON = rdd.flatMap(_._2.replace("}{", "}\n{").split("\n"))
val df = sqlContext.read.json(validJSON)
df.count()
df.select("id").show()
This is a riff on Antot's answer, which should handle nested JSON
input.toVector
.foldLeft((false, Vector.empty[Char], Vector.empty[String])) {
case ((true, charAccum, strAccum), '{') => (false, Vector('{'), strAccum :+ charAccum.mkString);
case ((_, charAccum, strAccum), '}') => (true, charAccum :+ '}', strAccum);
case ((_, charAccum, strAccum), char) => (false, charAccum :+ char, strAccum)
}
._3
Basically what it does is split the data into a Vector[Char], and uses foldLeft to aggregate the input into substrings. The trick is to keep track of just enough information about the previous character to figure out if a { marks the start of a new object.
I used this input to test it (basically the OP's sample input, with a nested object thrown in):
val input = """{"id":"2-2-3","key":{ "test": "value"}}{"id":"2-2-3","key":"value"}{"id":"2-2-3","key":"value"}{"id":"2-2-3","key":"value"}{"id":"2-2-3","key":"value"}"""
And got this result, which looks good:
Vector({"id":"2-2-3","key":{ "test": "value"}},
{"id":"2-2-3","key":"value"},
{"id":"2-2-3","key":"value"},
{"id":"2-2-3","key":"value"})
The problem with the original approach is the call _._2.replace("}{", "}\n{", which creates another huge string from the input one, with new line chars inserted, which is then split once again into an array.
An improvement is possible by minimizing the creation of intermediate strings and retrieving the target ones as soon as possible. For this, we can play a bit with substrings:
val validJson = rdd.flatMap(rawJson => {
// functions extracted to make it more readable.
def nextObjectStartIndex(fromIndex: Int):Int = rawJson._2.indexOf('{', fromIndex)
def currObjectEndIndex(fromIndex: Int): Int = rawJson._2.indexOf('}', fromIndex)
def extractObject(fromIndex: Int, toIndex: Int): String = rawJson._2.substring(fromIndex, toIndex + 1)
// the resulting strings are put in a local buffer
val buffer = new ListBuffer[String]()
// init the scanning of the input string
var posStartNextObject = nextObjectStartIndex(0)
// main loop terminates when there are no more '{' chars
while (posStartNextObject != -1) {
val posEndObject = currObjectEndIndex(posStartNextObject)
val extractedObject = extractObject(posStartNextObject, posEndObject)
posStartNextObject = nextObjectStartIndex(posEndObject)
buffer += extractedObject
}
buffer
})
Please note that this approach would work only if the objects in the input JSON are not nested, supposing that all curly braces separate objects of same level.

Extracting data from RDD in Scala/Spark

So I have a large dataset that is a sample of a stackoverflow userbase. One line from this dataset is as follows:
<row Id="42" Reputation="11849" CreationDate="2008-08-01T13:00:11.640" DisplayName="Coincoin" LastAccessDate="2014-01-18T20:32:32.443" WebsiteUrl="" Location="Montreal, Canada" AboutMe="A guy with the attention span of a dead goldfish who has been having a blast in the industry for more than 10 years.
Mostly specialized in game and graphics programming, from custom software 3D renderers to accelerated hardware pipeline programming." Views="648" UpVotes="337" DownVotes="40" Age="35" AccountId="33" />
I would like to extract the number from reputation, in this case it is "11849" and the number from age, in this example it is "35" I would like to have them as floats.
The file is located in a HDFS so it comes in the format RDD
val linesWithAge = lines.filter(line => line.contains("Age=")) //This is filtering data which doesnt have age
val repSplit = linesWithAge.flatMap(line => line.split("\"")) //Here I am trying to split the data where there is a "
so when I split it with quotation marks the reputation is in index 3 and age in index 23 but how do I assign these to a map or a variable so I can use them as floats.
Also I need it to do this for every line on the RDD.
EDIT:
val linesWithAge = lines.filter(line => line.contains("Age=")) //transformations from the original input data
val repSplit = linesWithAge.flatMap(line => line.split("\""))
val withIndex = repSplit.zipWithIndex
val indexKey = withIndex.map{case (k,v) => (v,k)}
val b = indexKey.lookup(3)
println(b)
So if added an index to the array and now I've successfully managed to assign it to a variable but I can only do it to one item in the RDD, does anyone know how I could do it to all items?
What we want to do is to transform each element in the original dataset (represented as an RDD) into a tuple containing (Reputation, Age) as numeric values.
One possible approach is to transform each element of the RDD using String operations in order to extract the values of the elements "Age" and "Reputation", like this:
// define a function to extract the value of an element, given the name
def findElement(src: Array[String], name:String):Option[String] = {
for {
entry <- src.find(_.startsWith(name))
value <- entry.split("\"").lift(1)
} yield value
}
We then use that function to extract the interesting values from every record:
val reputationByAge = lines.flatMap{line =>
val elements = line.split(" ")
for {
age <- findElement(elements, "Age")
rep <- findElement(elements, "Reputation")
} yield (rep.toInt, age.toInt)
}
Note how we don't need to filter on "Age" before doing this. If we process a record that does not have "Age" or "Reputation", findElement will return None. Henceforth the result of the for-comprehension will be None and the record will be flattened by the flatMap operation.
A better way to approach this problem is by realizing that we are dealing with structured XML data. Scala provides built-in support for XML, so we can do this:
import scala.xml.XML
import scala.xml.XML._
// help function to map Strings to Option where empty strings become None
def emptyStrToNone(str:String):Option[String] = if (str.isEmpty) None else Some(str)
val xmlReputationByAge = lines.flatMap{line =>
val record = XML.loadString(line)
for {
rep <- emptyStrToNone((record \ "#Reputation").text)
age <- emptyStrToNone((record \ "#Age").text)
} yield (rep.toInt, age.toInt)
}
This method relies on the structure of the XML record to extract the right attributes. As before, we use the combination of Option values and flatMap to remove records that do not contain all the information we require.
First, you need a function which extracts the value for a given key of your line (getValueForKeyAs[T]), then do:
val rdd = linesWithAge.map(line => (getValueForKeyAs[Float](line,"Age"), getValueForKeyAs[Float](line,"Reputation")))
This should give you an rdd of type RDD[(Float,Float)]
getValueForKeyAs could be implemented like this:
def getValueForKeyAs[A](line:String, key:String) : A = {
val res = line.split(key+"=")
if(res.size==1) throw new RuntimeException(s"no value for key $key")
val value = res(1).split("\"")(1)
return value.asInstanceOf[A]
}

Access code file and line number from Scala macro?

How can I access the name of the code file and line number in a Scala macro? I looked at SIP-19 and it says it can be easily implemented using macros...
EDIT:
To clarify, I want the code file and line number of the caller. I already have a debug macro and I want to modify it to print the line number and file name of whoever calls debug
You want c.macroApplication.pos, where c is for Context.
c.enclosingPosition finds the nearest macro on the stack that has a position. (See the other answer.) For instance, if your assert macro generates a tree for F"%p: $msg" but doesn't assign a position, the F macro would be positionless.
Example from a string interpolator macro, F"%p":
/* Convert enhanced conversions to something format likes.
* %Q for quotes, %p for position, %Pf for file, %Pn line number,
* %Pc column %Po offset.
*/
private def downConvert(parts: List[Tree]): List[Tree] = {
def fixup(t: Tree): Tree = {
val Literal(Constant(s: String)) = t
val r = "(?<!%)%(p|Q|Pf|Po|Pn|Pc)".r
def p = c.macroApplication.pos
def f(m: Match): String = m group 1 match {
case "p" => p.toString
case "Pf" => p.source.file.name
case "Po" => p.point.toString
case "Pn" => p.line.toString
case "Pc" => p.column.toString
case "Q" => "\""
}
val z = r.replaceAllIn(s, f _)
Literal(Constant(z)) //setPos t.pos
}
parts map fixup
}
If you mean file name and line number of the current position in the source code, for 2.10, my answer to that SO question is what your looking for:
def $currentPosition:String = macro _currentPosition
def _currentPosition(c:Context):c.Expr[String]={ import c.universe._
val pos = c.enclosingPosition
c.Expr(Literal(Constant(s"${pos.source.path}: line ${pos.line}, column ${pos.column}")))
}
That should work with 2.11 as well, although this way of creating the AST seems deprecated.
You can also have a look at that excerpt of my project Scart; it's how I use this technique to emit traces for debugging purposes.
The example in 'Writing Scala Compiler Plugins' shows how to access the line name and current number of the current position, as the others answers have mentioned.
http://www.scala-lang.org/old/node/140
In addition to the answers above, you can also get the position from the AST returned from a CompilationUnit.
For example:
def apply(unit: CompilationUnit) {
// Get the AST
val tree = unit.body
// Get the Position
// Scala.util.parsing.input.Position
val myPos = tree.pos
// Do something with the pos
unit.warning(pos, "Hello world")
}

Liftweb - Multiple ValueCell State Change

In my application I have use some "data" ValueCell (something like 20) and I would like to create a ValueCell which would be used to detect if any of my "data" ValueCell was updated . So I would like this cell to change whenever one of the other cells are changed.
Here is a simple code example
class StringFilter {
val referenceList = "foo"::"bar"::"scala"::"lift"::Nil
val length = ValueCell[Int](3)
val content = ValueCell[String]("")
//Here I put some functions to update length or prefix on my webpage
def filter(s:String):Boolean = (s.length==length.get)&&(s.contains(content.get))
val changed =ValueCell[???](???)
val results= changed.lift(referenceList.filter)
}
What should I put instead of ???? I am also open to solutions which are not using ValueCells, even if I will in the end need some cells because I have to use WiringUI.
Edit: lengthand contentdon't need to be cells but they need to be settable
Edit: After some more research I came to an idea: implement a case class like SeqCellbut which would not take a type for the Cells in parameter, and for an arbitrary number of cells. Is it possible?
Here is the implementation of SeqCell:
final case class SeqCell[T](cells: Cell[T]*) extends Cell[Seq[T]] {
cells.foreach(_.addDependent(this))
/**
* The cell's value and most recent change time
*/
def currentValue: (Seq[T], Long) = {
val tcv = cells.map(_.currentValue)
tcv.map(_._1) -> tcv.foldLeft(0L)((max, c) => if (max > c._2) max else c._2)
}
/**
* If the predicate cell changes, the Dependent will be notified
*/
def predicateChanged(which: Cell[_]): Unit = notifyDependents()
}
Edit: In scala Cellis not covariant, so it seems like I won't be able to make a SeqCell out of my multiple typed cells. I would really appreciate a global solution for an arbitrary number of cells.
Check out FuncCell. It's just another cell that will determine its value as a function of one or more other cells. The link I gave is the companion object which has apply methods for 1-5 cells, corresponding to the existing FuncCell1 .. FuncCell5 implementations. When one of those cells changes value, the FuncCell will update its own value- you would then hook up the WiringUI with your FuncCell.
Please forgive any syntax errors, I don't have an IDE open to check myself...
val changed: Cell[List[String]] = FuncCell(length, content){(len,con) =>
def filter(s: String) = (s.length == len) && (s.contains(con))
referenceList.filter(filter _)
}
If that's right, then changed is now a Cell whose value will reflect the result of calling referenceList.filter
In response to your edit regarding the SeqCell, I can think of two solutions:
1) Use Any as the type parameter in the SeqCell
val cell1: ValueCell[Int] = ...
val cell2: ValueCell[String] = ...
val cell3: ValueCell[Stuff] = ...
...
val combined: SeqCell[Any] = SeqCell(cell1, cell2, cell3, ...)
val results = FuncCell(combined){ seq: Seq[Any] => ... }
2) Combine the intermediate cells into tuples so that you can use the existing FuncCell implementations.
val intermediate1: Cell[(Int,String)] =
FuncCell(cell1,cell2){(a:Int, b:String) => a -> b}
val results =
FuncCell(intermediate1, cell3){(i: (Int, String), s: Stuff) => ...}