This page is no longer maintained — Please continue to the home page at www.scala-lang.org

variable type parameters

2 replies
Stephen Haberman
Joined: 2009-07-17,
User offline. Last seen 42 years 45 weeks ago.

Hi,

Is there a good way to define functions that work over N number of type
parameters? I think the answer is yes, along the lines of the HList
heterogeneous list and/or higher-kinded generics, but all I have is a
hunch and am not quite sure where to start.

My use case is taking a regular log statement like:

log.error("some message arg1 is {} arg2 is {}", arg1, arg2);

Which is currently just `error(String, Object...)`and change it to:

val error = new Error[Int, String]("some message ...")

Then later use error as:

error(arg1, arg2) --> error.apply(arg1, arg2)

I can work this out by defining Error0, Error1[T], Error2[T,U], etc.,
but it'd be nice to build it up, e.g.:

val error = Error("Some message").with[Int].with[String]

Or something like that where Error starts with its apply method having
no parameters, then with each call to with, we return a new type with
n+1 parameters to its apply method, with the n+1-th parameter being
strongly typed to whatever T got passed to the latest with method.

I need to re-read some mono/scalaz/HList stuff, but would appreciate a
hint as well.

Thanks,
Stephen

geoff
Joined: 2008-08-20,
User offline. Last seen 1 year 25 weeks ago.
Re: variable type parameters

Is this the sort of thing you have in mind?

trait Error {
type With[T] <: Error
def With[T]: With[T]
}

object Error {
def apply(x: String) = new Error0(x)
}

class Error0(val x: String) {
type With[T] = Error1[T]
def With[T] = new Error1[T](x)
def apply() = x
}

class Error1[A](val x: String) {
type With[T] = Error2[A,T]
def With[T] = new Error2[A,T](x)
def apply(a: A) = x + ":" + a
}

class Error2[A,B](val x: String) {
type With[T] = Error3[A,B,T]
def With[T] = new Error3[A,B,T](x)
def apply(a: A, b: B) = x + ":" + a + ":" + b
}

class Error3[A,B,C](val x: String) {
type With[T] = Nothing
def With[T] = error("no more")
def apply(a: A, b: B, c: C) = x + ":" + a + ":" + b + ":" + c
}

You can use it like Error("abcd").With[Int].With[String](123,"xyz")

Stephen Haberman
Joined: 2009-07-17,
User offline. Last seen 42 years 45 weeks ago.
Re: variable type parameters

> Is this the sort of thing you have in mind?

> class Error0(val x: String) {
> type With[T] = Error1[T]
> def With[T] = new Error1[T](x)
> def apply() = x
> }

[snip]

> You can use it like Error("abcd").With[Int].With[String](123,"xyz")

Yes, except I wanted to be fancy and avoid a lot of ErrorX classes. You
are right, this is probably the most practical way to do this.

I was attempting to have some Error[T] where T could be no args, 1 args,
or n args depending on the context.

HList's HCons seems to do this:

http://jnordenberg.blogspot.com/2008/08/hlist-in-scala.html

Though I haven't had the time to read/understand/adapt this approach to
what I want to do. Though given how quick & easy Error0/Error1/etc. is,
I will likely end up going that route anyway.

Thanks,
Stephen

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland