1

Given a made-up F type-class:

scala> trait F[A] {} defined trait F 

and this definition, which uses a context bound to require that the input A has a type-class instance of F:

scala> def f[A : F](x: A) = ??? f: [A](x: A)(implicit evidence$1: F[A])Nothing 

I defined a Person and type-class instance:

scala> case class Person(name: String) defined class Person scala> implicit val person: F[Person] = new F[Person] {} person: F[Person] = $anon$1@262b2c86 

And the following compiles:

scala> f(Person("foo")) scala.NotImplementedError: an implementation is missing 

But, there's no String implementation, so it fails.

scala> f("foobar") <console>:17: error: could not find implicit value for evidence parameter of type F[String] f("foobar") ^ 

I then defined an F[String] using:

scala> implicit def fInstance(x: String) = new F[String] {} fInstance: (x: String)F[String] 

But, I can't run:

scala> f("foobar") <console>:18: error: could not find implicit value for evidence parameter of type F[String] f("foobar") ^ 

since I do not have an implicit F[String], but rather a String => F[String].

What's the proper way to use such an implicit def to meet the F[String] constraint, i.e. call the f function successfully with a type of String?

I got it to work via:

scala> implicit val x: F[String] = implicitly[String => F[String]].apply("foobar") x: F[String] = $anon$1@7b7fdc8 scala> f("foobar") scala.NotImplementedError: an implementation is missing at scala.Predef$.$qmark$qmark$qmark(Predef.scala:230) at .f(<console>:12) ... 33 elided 

But I'm not sure if it's the right/clean way to do it.

4
  • This is really hard to answer without knowing what information and operations the type class is meant to capture, but given this particular F, you could define a String instance in exactly the same way you did the Person instance. Commented Sep 23, 2016 at 18:07
  • For this case, I can only construct an F[String] if provided a String, i.e. an F[String] instance depends upon a String argument. Commented Sep 23, 2016 at 18:08
  • As a follow-up, is it bad to use an implicit outside of a companion class, i.e. an orphan implicit instance? Commented Sep 23, 2016 at 18:09
  • fInstance is not a typeclass instance, but an implicit conversion Commented Sep 23, 2016 at 18:24

3 Answers 3

1

You defined an implicit conversion. If you want to use a def to provide typeclass instances you just write the same as you'd write an implicit val but replace val with def.

implicit def fInstance = new F[String] {} 

Normally you only use a def if you need type parameters, like here.

implicit def fInstance[A] = new F[List[A]] {} 

Or

implicit def fInstance[A](implicit ev: F[A]) = new F[List[A]] {} 
Sign up to request clarification or add additional context in comments.

Comments

0

Your fInstance defines an implicit conversion, i.e. a way to turn a String into F[String]. For generating a typeclass instance, a method accepting implicit parameters can be used:

implicit def fInstance(implicit x: String) = new F[String] {} 

it is typically used in FP libraries to derive one typeclass from another:

implicit def optionMonoid[A](implicit S: Semigroup[A]): Monoid[Option[A]] = ??? // or, which is the same // implicit def optionMonoid[A: Semigroup]: Monoid[Option[A]] = ??? 

The idea is that F[String] can operate on any String in general, not being dependent on actual arguments provided into function. Of course, you can always provide instances explicitly:

f("foobar")(new F[String] { }) 

As a follow-up, the important part of typeclasses is that you can define them ad-hoc, i.e. not having access to definitions of F and String at all, and you are forced to scope implicits in Scala and import them, so it's totally ok.

2 Comments

and you are forced to scope implicits in Scala and import them, so it's totally ok. Could you please say more as to how this statement applies (or does not) to orphan implicit's?
@KevinMeredith you are not allowed to simply write a def or val in the source (if it's application code and not Scala script) — it has to belong to an object or class. So you have to go with object Implicits { implicit def fString: F[String] = ??? }, but you cannot use it in other code, unless you do import Implicits.fString in it before using.
0

Here is a simpler version of your definition (and you can remove implicit from fInstance):

implicit val singleFInstance: F[String] = fInstance("") // or fInstance("foobar"), etc. 

Whether this is the right thing to do, very much depends on what F and f are supposed to mean.

But generally speaking: if F is really a type-class, fInstance(string) gives different results depending on the string (not just different instances, but different behavior), and f's signature is correct, then this is wrong and you should accept that calling f("foobar") isn't meaningful.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.