Skip to content

Add ability to declare pattern matched values as implicit? #4131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ryanstull opened this issue Mar 17, 2018 · 4 comments
Closed

Add ability to declare pattern matched values as implicit? #4131

ryanstull opened this issue Mar 17, 2018 · 4 comments

Comments

@ryanstull
Copy link

ryanstull commented Mar 17, 2018

I have a suggestion for a potential syntax enhancement to Dotty. Here's the issue I'm having:

trait A[T]
trait B[T]
trait C[T] extends A[T] with B[T]
case class concreteC[T](a: T) extends C[T]

case class needsA[T](value: T)(implicit a: A[T]){

//If our A is actually an instance of C then we can do other stuff!
	def foo: Unit = a match { case c: C[T] =>

		// implicit val c2 = c

		implicitly[B[T]]
	}
}

object Main{

	def main(args: Array[String]): Unit = {

		implicit val cOfInt = concreteC(4)

		val needA = needsA(3)
		needA.foo
		println("Good")
	}
}

Here's a link to the code in scastie

if you run the above code it will fail because it can't find an implicit parameter B[T], even though the C[T] that we pattern matched on is guaranteed to also be a B[T]. This happens in 2.12 and Dotty

This will work however if you un-comment the line that reassigns c to an implicit; so all that is needed is a way to mark the pattern matched value as implicit. I was thinking something like this:

def foo: Unit = a match { case implicit c: C[T] =>
	implicitly[B[T]]
}

Hopefully it won't be too big a change since it seems this already works for parameters to lambda functions, as shown here on line 19.

I'm not sure if we could / would want to add this for all variables extracted from patterns? Such as...

val seq = Seq("Hello", "World")

seq match {
	case implicit head :: tail => {
		implicitly[String]
		println("Works")
	}
}

or...

val seq = (123,"Words",true)

seq match {
	case (a: Int,b: String,implicit c: Boolean) => {
		implicitly[Boolean]
		println("Works")
	}
}

Please let me know your thoughts!

@Blaisorblade
Copy link
Contributor

Off the top of my head: that seems an interesting idea, and I've desired similar things when transforming case classes with implicit parameters. (See below). It also seems to make the language more regular — many other binders can be implicit, why not binders in pattern matchers?

Making up (too) quickly an example of map fusion (which likely won't work, but I hope it conveys the idea; not sure it's better than your example):

trait Exp[T]
...
case class MapExpr[A, B, That](f: Exp[A => B], xs: Exp[Traversable[A]])(implicit val cbf: CanBuildFrom[Traversable[A], B, That]) extends Exp[That] //sorry oversimplified, I should use TraversableLike and F-bounds

def mapFusion[T](exp: Exp[T]) = exp match {
  case MapExpr(g, MapExpr(f, xs)(implicit cbf1))(implicit cbf2) =>
    //figure out how to combine the CanBuildFrom. Probably doesn't work as-is, but hopefully you believe me such implicit bindings could be useful
    MapExpr(f andThen g, xs)
}

For better examples I'd have to look at https://github.com/ps-mr/LinqOnSteroids.

But maybe I miss some issue for users. Maybe gather more feedback at https://contributors.scala-lang.org or gitter first?

To help people see the value of the idea, better examples might help — they should involve more natural candidates for implicits — for instance, instances of Ord[T], or other similar "typeclass"-like implicits.

@ryanstull
Copy link
Author

Cool! Yeah I agree we'll probably need a pretty straightforward example... I'll make one then make a post on the contributors site.

@smarter
Copy link
Member

smarter commented Mar 17, 2018

But maybe I miss some issue for users. Maybe gather more feedback at https://contributors.scala-lang.org or gitter first?

Agreed. To keep the issue tracker manageable (cf #3706) I think it's best to leave this sort of open discussions out of it, so I'll close this issue for now.

@smarter smarter closed this as completed Mar 17, 2018
@ryanstull
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants