0
votes

I want to do something like this:

def fold[C[A]](implicit ev: Foldable[A]): A

I am getting not found: type A

I know, I can do this instead:

def fold[C[_], A: Foldable]: A

But, I would rather invoke as fold[List[Int]] than fold[List, Int]

2
How is fold useful without something to fold? Two type parameters is fine when you can rely on type inference: def fold[A: Foldable, C[_]](ca: C[A]) = ???Michael Zajac
@m-z: This was just a factitious example. Replace the word fold with fooBarpathikrit
I know, but typically you would have a parameter of C[A] which would allow you to infer the type parameters rather than supplying them manually. In other words, I'm pretty sure there is no way to achieve what you ask with only one type parameter.Michael Zajac
On scope: Since the names of higher-order type parameters are thus often irrelevant, they may be denoted with a ‘_’, which is nowhere visible. scala-lang.org/files/archive/spec/2.11/…som-snytt
Typelevel wants the same thing, where there are two type params but you supply only one and the other is inferred, curried like value params.som-snytt

2 Answers

1
votes

I played a bit with it and came up with a helper type class:

trait Helper[M[_], CA] {
  type C[_]
  type A
  implicit def ma: M[A]
}
object Helper {
  implicit def instance[M0[_], C0[_], A0](implicit ma0: M0[A0]) = new Helper[M0, C0[A0]] {
    type C[X] = C0[X]
    type A = A0
    val ma: M0[A0] = ma0
  }
}

I know the names are pretty generic, I'd suggest finding more meaningful names.

Now instead of requiring an implicit of type Foldable[A] you require instead an implicit of Helper[Foldable, CA] where CA is the type that must match against List[Int] in your example:

def fold[CA](implicit helper: Helper[Foldable, CA]): helper.A

As an example:

def fold[CA](implicit helper: Helper[Foldable, CA]): helper.A = {
  import helper._
  println(implicitly[Foldable[A]])
  null.asInstanceOf[A]
}

scala> :paste
// Entering paste mode (ctrl-D to finish)
case class Foldable[A](name: String)
implicit val stringFoldable = Foldable[String]("String")
implicit val intFoldable = Foldable[Int]("Int")
implicit val floatFoldable = Foldable[Float]("Float")

def fold[CA](implicit helper: Helper[Foldable, CA]): helper.A = {
  import helper._
  println(implicitly[Foldable[A]])
  null.asInstanceOf[A]
}
// Exiting paste mode, now interpreting.

defined class Foldable
stringFoldable: Foldable[String] = Foldable(String)
intFoldable: Foldable[Int] = Foldable(Int)
floatFoldable: Foldable[Float] = Foldable(Float)
fold: [CA](implicit helper: Helper[Foldable,CA])helper.A

scala> fold[List[String]]
Foldable(String)
res0: String = null

scala> fold[List[Int]]
Foldable(Int)
res1: Int = 0

scala> fold[List[Float]]
Foldable(Float)
res2: Float = 0.0
1
votes

Here's what I came up with:

trait Foo[T, A]

implicit def makeFoo[A, M[_]] = new Foo[M[A], A] {}

class Helper[T] {
  def apply[A]()(implicit ev: Foo[T, A]) = ev 
}

def bar[T] = new Helper[T]

bar[List[Int]]()
//Foo[List[Int],Int] = $anon$1@7edf6563

The empty pair of parens might not be ideal if you really want an a no-arg method, but I can't see how to get around that at the moment.