Implicit conversion not working - scala

Why is the following implicit method not applied? And how can I achieve to automatically convert an instance of X to an instance of Y while having an implicit Conversion[X,Y] in scope.
trait Conversion[X, Y] {
def apply(x: X): Y
}
implicit object Str2IntConversion extends Conversion[String, Int] {
def apply(s: String): Int = s.size
}
implicit def convert[X, Y](x: X)(implicit c: Conversion[X, Y]): Y = c(x)
val s = "Hello"
val i1: Int = convert(s)
val i2: Int = s // type mismatch; found: String required: Int

Make your conversion extend Function1, then you don't need the helper method anymore:
trait Conversion[X, Y] extends (X => Y) {
def apply(x: X): Y
}
// unchanged
implicit object Str2IntConversion extends Conversion[String, Int] {
def apply(s: String): Int = s.size
}
// removed convert
// unchanged
val s = "Hello"
val i1: Int = convert(s)
val i2: Int = s

Related

generalize Int -> Int, Int-> String, String -> String, String -> Int

I have 4 methods with one logic and 4 possible type mapping:
def convertStringToString(in: String): String = ???
def convertIntToString(in: Int): String = ???
def convertIntToInt(in: Int): Int = ???
def convertStringToInt(in: String): Int = ???
I want to generalize input and output type and write logic in one methods. Tried to generelize input parameter:
def convertToInt[IN](in: IN): Int = in match {
case x: String if x.forall(_.isDigit) => x.toInt
case y: Int => y
case _ => 0
}
def convertToString[IN](in: IN): String = convertToInt[IN](in).toString
Could you help me to generalize second:
def convertToInt[IN, OUT](in: IN): OUT = ???
If you really wanted to, you could have something typeclass-based:
def convert[I, O](in: I)(implicit c: ConversionRule[I, O]): O = {
if (c.isConvertible(in)) c.convert(in)
else c.zero
}
trait ConversionRule[I, O] {
def isConvertible(in: I): Boolean
def convert(in: I): O
def zero: O // Could possibly derive the zero from, e.g., a cats Monoid instance where such exists
}
The eagle-eyed may notice that the isConvertible/convert methods match the contract of PartialFunction[I, O]'s isDefinedAt/apply, so may as well just use PartialFunction (and rewrite convert with isDefinedAt/apply)
trait ConversionRule[I, O] extends PartialFunction[I, O] {
def zero: O
}
zero can be implemented in terms of PartialFunction.applyOrElse, but for the case where zero is constant (which is the case where referential transparency is preserved), this is much faster.
Smart constructors can be defined:
object ConversionRule {
def apply[I, O](zeroValue: O)(pf: PartialFunction[I, O]): ConversionRule[I, O] =
new ConversionRule[I, O] {
override def apply(i: I): O = pf(i)
override def isDefinedAt(i: I): Boolean = pf.isDefinedAt(i)
val zero: O = zeroValue
}
def totalConversion[I, O](f: I => O): ConversionRule[I, O] =
new ConversionRule[I, O] {
override def apply(i: I) = f(i)
override def isDefinedAt(i: I) = true
override def zero: O = throw new AssertionError("Should not call since conversion is defined")
}
// Might want to put this in a `LowPriorityImplicits` trait which this object extends
implicit def identityConversion[I]: ConversionRule[I, I] =
totalConversion(identity)
}
identityConversion means that a convertIntToInt gets automatically generated.
convertStringToInt can then be defined as
implicit val stringToIntConversion = ConversionRule[String, Int](0) {
case x if x.forAll(_.isDigit) => x.toInt
}
One can define a toString based conversion (basically the non-lawful Show proposed for alleycats):
implicit def genericToString[I]: ConversionRule[I, String] =
ConversionRule.totalConversionRule(_.toString)
And it should then be possible to define a stringViaInt ConversionRule derivation like:
implicit def stringViaInt[I, O](implicit toInt: ConversionRule[I, Int]): ConversionRule[I, String] =
convert(convert(in)(toInt))
The only really useful thing this provides is an opt-in to usage of implicit conversions. Whether that's enough of a gain to justify? shrug
(Disclaimer: only the scala compiler in my head has attempted to compile this)

Type safe type combinations with shapeless

Having the following code:
import shapeless.{::, Generic, HList, HNil, Lazy}
object Problem {
trait In {
def bar: Double
}
trait A {
def foo: Int
type I <: In
}
/////////////////////////////////////////////////////
final case class A1In(d: Double) extends In {
override def bar: Double = 1.1 + d
}
final case class A1() extends A {
override def foo: Int = 1
override type I = A1In
}
final case class A2In(d: Double) extends In {
override def bar: Double = 1.1 + d
}
final case class A2() extends A {
override def foo: Int = 1
override type I = A2In
}
final case class AListIn[T <: HList](items: T)(implicit ev: isIn[T]) extends In {
override def bar = 1.1
}
final case class AList[T <: HList](items: T)(implicit ev: isA[T]) extends A {
override def foo: Int = 555
override type I = AListIn[???]
}
trait isA[T] {
def aux_foo(value: T): Int
}
trait isIn[T] {
def aux_bar(value: T): Double
}
/////////////////////////////////////////////////////
def alloc(a: A): In = ????
def usage() = {
val a1: A1 = A1()
val a2: A2 = A2()
val l: AList[::[A1, ::[A2, ::[A1, HNil]]]] = AList(a1 :: a2 :: a1 :: HNil)
val a1In: A1In = A1In(1.2)
val a2In: A2In = A2In(9.3)
val lIn: AListIn[::[A2In, ::[A1In, HNil]]] = AListIn(a2In :: a1In :: HNil)
}
}
How can I fix it so it works as expected?
E.g how do I get correct type in place of ??? which is a proper type HList being result of applying isA -> isIn type mapping. The mapping must follow the natural association of A -> In mapping defined as type I <: In in trait A
And how to implement alloc function which for any concrete instance of In will produce corresponding instance of A?
Should concrete implementations of In be path dependent types of corresponding As?
Below is the code for isA the code for isIn is analogous
trait isA[T] {
def aux_foo(value: T): Int
}
object isA {
// "Summoner" method
def apply[T](implicit enc: isA[T]): isA[T] = enc
// "Constructor" method
def instance[T](func: T => Int): isA[T] = new isA[T] {
override def aux_foo(value: T): Int = func(value)
}
implicit def a1Encoder: isA[A1] = instance(i => 4)
implicit def a2Encoder: isA[A2] = instance(i => 9)
implicit def hnilEncoder: isA[HNil] = instance(hnil => 0)
implicit def hlistEncoder[H, T <: HList](implicit
hInstance: Lazy[isA[H]],
tInstance: isA[T]
): isA[H :: T] = instance {
case h :: t => hInstance.value.aux_foo(h) + tInstance.aux_foo(t)
}
implicit def genericInstance[A, R](implicit
generic: Generic.Aux[A, R],
rInstance: Lazy[isA[R]]
): isA[A] = instance { value => rInstance.value.aux_foo(generic.to(value)) }
}

Lifting a function which takes implicit parameter using functor (Scalaz7)

Just started learning Scalaz. Here is my code
trait Monoid[A] {
def mappend(a1: A, a2: A): A
def mzero: A
}
object Monoid {
implicit val IntMonoid: Monoid[Int] = new Monoid[Int] {
def mappend(a1: Int, a2: Int): Int = a1 + a2
def mzero: Int = 0
}
implicit val StringMonoid: Monoid[String] = new Monoid[String] {
def mappend(a1: String, a2: String): String = a1 + a2
def mzero: String = ""
}
}
trait MonoidOp[A] {
val F: Monoid[A]
val value: A
def |+|(a2: A): A = F.mappend(value, a2)
}
object MonoidOp{
implicit def toMonoidOp[A: Monoid](a: A): MonoidOp[A] = new MonoidOp[A]{
val F = implicitly[Monoid[A]]
val value = a
}
}
I have defined a function (just for the sake of it)
def addXY[A: Monoid](x: A, y: A): A = x |+| y
I want to lift it so that it could be used using Containers like Option, List, etc. But when I do this
def addXYOptioned = Functor[Option].lift(addXY)
It says error: could not find implicit value for evidence parameter of type scalaz.Monoid[A]
def addOptioned = Functor[Option].lift(addXY)
How to lift such functions?
Your method addXY needs a Monoid[A] but there is no Monoid[A] in scope when used in addXYOptioned, so you also need to add the Monoid constraint to addXYOptioned.
The next problem is that Functor.lift only lifts a function A => B, but we can use Apply.lift2 to lift a function (A, B) => C.
Using the Monoid from Scalaz itself :
import scalaz._, Scalaz._
def addXY[A: Monoid](x: A, y: A): A = x |+| y
def addXYOptioned[A: Monoid] = Apply[Option].lift2(addXY[A] _)
We could generalize addXYOptioned to make it possible to lift addXY into any type constructor with an Apply instance :
def addXYApply[F[_]: Apply, A: Monoid] = Apply[F].lift2(addXY[A] _)
addXYApply[List, Int].apply(List(1,2), List(3,4))
// List[Int] = List(4, 5, 5, 6)
addXYApply[Option, Int].apply(1.some, 2.some)
// Option[Int] = Some(3)

Using implicit objects within classes

I am trying to write code to represent polynomials within Scala. I need this code to be type polymorphic, so I am using implicits to deal with different types. I have:
case class Mono[T](degree: Int, coeff: T) {
def Degree: Int = return degree
def Coeff: T = return coeff
}
class Poly[T](private val terms: List[Mono[T]]) {
trait Semiring[T] {
def add(x:T, y:T): T
def mul(x:T, y:T): T
def exponent(x: T, n:Int): T
val unitA: T
}
implicit object IntSemiring extends Semiring[Int] {
def add(x: Int, y: Int): Int = x+y
def mul(x: Int, y: Int): Int = x*y
def exponent(x: Int, n:Int): Int = if(n==0) 1 else x*exponent(x, n-1)
val unitA: Int = 0
}
implicit object SetSemiring extends Semiring[Set[Int]] {
def add(x: Set[Int], y: Set[Int]): Set[Int] = x.union(y)
def mul(x: Set[Int], y: Set[Int]): Set[Int] = x.intersect(y)
def exponent(x: Set[Int], n: Int): Set[Int] = x
val unitA: Set[Int] = Set()
}
def eval(x: T)(implicit r: Semiring[T]): T = {
var termlist = terms
var sum = r.unitA
var expression = terms
while(!termlist.isEmpty) {
val term = expression.head
val power = r.exponent(x, term.Degree)
val termval = r.mul(power, term.Coeff)
sum = r.add(sum, termval)
termlist = termlist.tail
}
return sum
}
def add(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...
def mul(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...
}
I chopped out a few functions for brevity there. This compiles fine but when I try and use it I get some strange errors:
scala> val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
p1: Poly[Int] = Poly#450ae3fb
scala> p1 eval 3
<console>:9: error: could not find implicit value for parameter r: p1.Semiring[Int]
p1 eval 3
^
I'm not sure how to fix it. Am I defining the implicit objects in the wrong place? I tried moving them outside the class but then the complier fails. Is there something else I need to do to get it to work properly?
Implicit resolution is done at the location where you call the function, not where you define it. You should import your implicits before calling p1.eval:
val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
import p1._
p1 eval 3
Since your implicits are not really bound to an instance of Poly, you can define them outside Poly.
If you don't want to import explicitly the Semiring implicits, you can define them in the companion object of Semiring since Scala search for matching implicits in the companion object when they are missing:
case class Mono[T](degree: Int, coeff: T) {
def Degree: Int = return degree
def Coeff: T = return coeff
}
class Poly[T](private val terms: List[Mono[T]]) {
def add(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...
def mul(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...
}
trait Semiring {
def add(x:T, y:T): T
def mul(x:T, y:T): T
def exponent(x: T, n:Int): T
val unitA: T
}
object Semiring {
implicit object IntSemiring extends Semiring[Int] {
def add(x: Int, y: Int): Int = x+y
def mul(x: Int, y: Int): Int = x*y
def exponent(x: Int, n:Int): Int = if(n==0) 1 else x*exponent(x, n-1)
val unitA: Int = 0
}
implicit object SetSemiring extends Semiring[Set[Int]] {
def add(x: Set[Int], y: Set[Int]): Set[Int] = x.union(y)
def mul(x: Set[Int], y: Set[Int]): Set[Int] = x.intersect(y)
def exponent(x: Set[Int], n: Int): Set[Int] = x
val unitA: Set[Int] = Set()
}
}
Then you don't need to import them anymore:
val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
p1 eval 3

How can I remove this extra type parameter?

I currently have:
class X[+T: Numeric](val x: T)
abstract class M[N: Numeric, T <: X[N]] { // <- I'd like to remove N.
def apply(x: Int): T
final def row = (1 to 10).map(this(_))
}
I use it like this:
class Y(x: Double, val y: Double) extends X[Double](x)
class Z extends M[Double, Y] { // <- So that this is simpler.
def apply(x: Int) = new Y(0.0, 0.0)
}
It works like this:
object testapp {
// row is properly polymorphic, allowing access to Y.y
def main(args: Array[String]): Unit = (new Z).row.map(r => println(r.y))
}
I want Z to be simpler so that I can use M like:
class Z extends M[Y] {
def apply(x: Int) = new Y(0.0, 0.0)
}
or, even better:
class Z extends M[Double] { // i.e. Meaning apply can return
def apply(x: Int) = new Y(0.0, 0.0) // any subclass of X[Double]
}
Here are my Gist iterations to reach this point.
A third way in type params vs type members is to use both.
An advantage of a type member is that it doesn't pollute the signature of child classes. The type member can remain abstract if it is superfluous (even in a concrete class); and only the bottom class must define it if necessary.
import scala.collection.immutable.IndexedSeq
class X[+T: Numeric](val x: T)
abstract class M[+A: Numeric] {
type W <: X[A]
def apply(x: Int): W
final def row: IndexedSeq[W] = (1 to 10) map apply
def sumx: A = { // in terms of the underlying Numeric
val n = implicitly[Numeric[A]]
n fromInt (0 /: row)((s,w) => s + (n toInt w.x))
}
}
class Y(x: Double, val y: Double) extends X[Double](x)
class Z extends M[Double] {
type W = Y
def apply(x: Int) = new Y(0.0, 0.0)
}
def main(args: Array[String]): Unit = (new Z).row foreach (Console println _.y)
You didn't really need class M here:
class X[+T: Numeric](val x: T)
def row[W <: X[_]](c: => Int => W) = (1 to 10).map(c)
class Y(x: Double, val y: Double) extends X[Double](x)
def z = row(_ => new Y(0.0, 0.0))
def main(args: Array[String]): Unit = z.map(r => println(r.y))
If you want to keep M, you use same idea:
class X[+T: Numeric](val x: T)
abstract class M[W <: X[_]] {
def apply(x: Int): W
final def row = (1 to 10).map(this(_))
}
class Y(x: Double, val y: Double) extends X[Double](x)
class Z extends M[Y] {
def apply(x: Int) = new Y(0.0, 0.0)
}
def main(args: Array[String]): Unit = (new Z).row.map(r => println(r.y))