I am reading the Scrap Your Boilerplate paper and trying to follow along by implementing the ideas in scala as best I can. However, I'm stuck on the very first function, the cast, which is used to take a value and attempt to cast it to another type in an Option, obviously a Some if the cast is successful, and None otherwise. I have a version of it working with the following code:
trait Cast[A, B]:
def apply(a: A): Option[B]
object Cast:
given cSome[A, B](using t: A =:= B): Cast[A, B] with
def apply(a: A) = Some(t(a))
given cNone[A, B](using t: NotGiven[A =:= B]): Cast[A, B] with
def apply(a: A) = None
This works when types are statically known. Trying the examples from the paper:
val maybeChar = summon[Cast[Char, Char]]('a') // Some(a)
val maybeBool = summon[Cast[Char, Boolean]]('a') // None
val maybeBool2 = summon[Cast[Boolean, Boolean]](true) // Some(true)
However, when I try to clean up the ergonomics a bit so that we can rely on type inference as in the examples in the paper with a generic helper defined as such:
def cast[A, B](a: A): Option[B] = summon[Cast[A, B]](a)
I'm getting only Nones, meaning the types are never being seen as the same:
val mc: Option[Char] = cast('a') // None
val mb: Option[Boolean] = cast('a') // None
val mb2: Option[Boolean] = cast(true) // None
The same happens even when I'm being explicit with the types:
val mc: Option[Char] = cast[Char, Char]('a') // None
val mb: Option[Boolean] = cast[Char, Boolean]('a') // None
val mb2: Option[Boolean] = cast[Boolean, Boolean](true) // None
I'm using scala 3.2. Is there any way to achieve this cast function with the less verbose ergonomics? I'm even more curious why what I have isn't working, especially with the explicit casting? I'm pretty sure shapeless is able to provide an SYB implementation in scala 2, albeit probably relying on macros. Can we do this in scala 3 without macros?
You missed an implicit parameter
def cast[A, B](a: A)(using Cast[A, B]): Option[B] = summon[Cast[A, B]](a)
// ^^^^^^^^^^^^^^^^
When doing implicit resolution with type parameters, why does val placement matter? (implicitly[X] vs. (implicit x: X) in Scala 2, summon[X] vs. (using X) in Scala 3)
Related
I've been wracking my head against this and I can't figure out if there is a way to properly do this.
I feel I know what the problem is, but don't know how to solve it.
I have a method:
implicit def combineAlg[A: Alg, B: Alg]: Alg[A with B] = ...
if I call it explicitly it works fine, however it never gets implied properly.
// works
implicit val comb: Alg[A with B] = combineAlg[A, B]
// doesn't work
implicit val comb: Alg[A with B] = implicitly[Alg[A with B]]
Through my debugging with -Xlog-implicits, I believe its calling combineAlg[A with B, Nothing].
I'm looking to find a way to do something like:
implicit def combineExpAlg[AB, A >: AB, B >: AB]
or
implicit def combineExpAlg[AB, A, B](implicit ev1: AB <:< A, ev2: AB <:< B)
so that it understands that it needs to split apart the "with", but neither helps.
Not sure if there is a way to do this, really its an experiment I'm doing for "object algebras" in Scala and I'm trying to see how to remove boilerplate.
It'd be awesome if there was a solution.
A dotty solution would also be acceptable, as I'm also implementing it there to see if some of the new features make it simpler.
In case more information is needed you can view the repository here
What I'm trying to change is algebra.combineExpAlg.
It will look like it's working because I define specific implicits in algebra.interpreters.package that specifically spell out each interpreter pair, which is what I'm trying to generalize.
The following code compiles:
trait Alg[T]
trait LowPriorityAlg {
implicit def bAlg: Alg[B0] = ???
}
object Alg extends LowPriorityAlg {
implicit def aAlg: Alg[A0] = ???
implicit def combineAlg[AB, A: Alg, B: Alg](implicit ev1: AB <:< A, ev2: AB <:< B): Alg[AB] = ???
}
trait A0
trait B0
val comb: Alg[A0 with B0] = Alg.combineAlg[A0 with B0, A0, B0]
val comb1: Alg[A0 with B0] = implicitly[Alg[A0 with B0]]
I'm working with Slick's GetResult typeclass and wanted to use Shapeless to derive instances of GetResult[Option[(A, B, C...)]]
What I want:
Given an implicit GetResult[Option[A]], GetResult[Option[B]], ...,
implicitly generate a GetResult[Option[(A, B, ...)]]
What I tried
trait CanGetOption[T] {
def getOption: GetResult[Option[T]]
}
object CanGetOption {
// convenience implicit resolver
def apply[T](implicit canGetOption: CanGetOption[T]): CanGetOption[T] = canGetOption
// base case: HNil
implicit val getHNilOption: CanGetOption[HNil] = from(GetResult { _ => Some(HNil) })
// recursion case: H :: Tail
implicit def getHConsOption[H, Tail <: HList](
implicit getHeadOption: GetResult[Option[H]],
canGetTailOption: CanGetOption[Tail]
): CanGetOption[H :: Tail] = from(GetResult[Option[H :: Tail]] { r =>
val headOpt = getHeadOption(r)
val tailOpt = canGetTailOption.getOption(r)
for(head <- headOpt; tail <- tailOpt) yield head :: tail
})
// generic case: A, given a A <-> Repr conversion
// I also tried moving this into a "LowPriorityImplicits" thing, just in case
implicit def getGenericOption[A, Repr <: HList](
implicit gen: Generic.Aux[A, Repr],
getReprOpt: CanGetOption[Repr]
): CanGetOption[A] = from(GetResult { r =>
val reprOpt = getReprOpt.getOption(r)
reprOpt.map(gen.from)
})
}
implicit def resolveOptionGetter[T: CanGetOption]: GetResult[Option[T]] =
CanGetOption[T].getOption
Problem:
When I've imported the above, the resolveOptionGetter doesn't seem to be considered when searching for implicits:
scala> implicitly[GetResult[Option[(Int, Int)]]]
<console>:19: error: could not find implicit value for parameter e: scala.slick.jdbc.GetResult[Option[(Int, Int)]]
implicitly[GetResult[Option[(Int, Int)]]]
^
scala> resolveOptionGetter[(Int, Int)]
res1: scala.slick.jdbc.GetResult[Option[(Int, Int)]] = <function1>
Why can't the compiler find resolveOptionGetter in the implicit search? What can I do to help it?
The thing is that slick.jdbc.GetResult is covariant. If it were invariant, types would be inferred correctly and implicits would be resolved.
A workaround is hiding covariant slick.jdbc.GetResult with custom invariant type alias GetResult. Remove import slick.jdbc.GetResult and write in your source file
type GetResult[T] = slick.jdbc.GetResult[T]
object GetResult {
def apply[T](implicit f: PositionedResult => T): GetResult[T] = slick.jdbc.GetResult.apply
}
Now implicitly[GetResult[Option[(Int, Int)]]] compiles. Tested in Scala 2.12.7 + Shapeless 2.3.3 + Slick 3.2.3.
Variance often makes troubles for implicit resolution:
https://github.com/scala/bug/issues/10099
https://github.com/locationtech/geotrellis/issues/1292
Implicit resolution with covariance
I am trying to write a Functor for Either for academic purposes in Scala. With help of higher-kinded types and type-projections, I managed to write an implementation for Either.
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
object Functor {
implicit def eitherFunctor[A] = new Functor[({type λ[α] = Either[A, α]})#λ] {
override def map[B, C](fa: Either[A, B])(f: B => C) = fa.map(f)
}
}
def mapAll[F[_], A, B](fa: F[A])(f: A => B)(implicit fe: Functor[F]): F[B] = fe.map(fa)(f)
val right: Either[String, Int] = Right(2)
mapAll(right)(_ + 2)
Now, the code above does not compile. I am not sure of the reason but the compilation error that I am getting is given below -
Error:(19, 16) type mismatch;
found : Either[String,Int]
required: ?F[?A]
Note that implicit conversions are not applicable because they are ambiguous:
both method ArrowAssoc in object Predef of type [A](self: A)ArrowAssoc[A]
and method Ensuring in object Predef of type [A](self: A)Ensuring[A]
are possible conversion functions from Either[String,Int] to ?F[?A]
mapAll(right)(_ + 2)
Can someone point what I am not doing right in the code above?
PS: Please do not suggest me to use kind-projector.
You've just been bitten by SI-2712. If you're using Scala >= 2.12.2 just add this line to your build.sbt:
scalacOptions += "-Ypartial-unification"
For other Scala versions you can use this plugin.
Either[+A, +B] is expecting two type parameters(as #Ziyang Liu said), so for your example actually need BiFunctor not Functor, BiFunctor accept two functors and bound the two types.
there is a Bifunctor from Scalaz
trait Bifunctor[F[_, _]] { self =>
////
/** `map` over both type parameters. */
def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D]
So you can use this Bifunctor like:
Bifunctor[Either].bimap(Right(1): Either[String, Int])(_.toUpperCase, _ + 1).println
Hope it's helpful for you.
As others said, what the compiler is trying to tell you is that the shapes of your types don't match. When you require an F[_], you're requiring a type constructor with a single type parameter, which Either[A, B] doesn't satisfy.
What we need to do is apply a type lambda when applying mapAll, same as we did when we created the instance of the Either functor:
val right: Either[String, Int] = Right(2)
mapAll[({type λ[α]=Either[String, α]})#λ, Int, Int](right)(_ + 2)
We've now squeezed in String and fixed it as the first argument, allowing the type projected type to only need to satisfy our alpha, and now the shapes match.
Of course, we can also use a type alias which would free us from specifying any additional type information when applying mapAll:
type MyEither[A] = Either[String, A]
val right: MyEither[Int] = Right(2)
mapAll(right)(_ + 2)
I can write a simple recursive polymorphic function:
object simpleRec extends Poly1 {
implicit def caseInt = at[Int](identity)
implicit def caseList[A, B](implicit ev: simpleRec.Case.Aux[A, B]) =
at[List[A]](_.headOption.map(simpleRec))
}
This seems to largely do what I want; however, I seem to be getting a nonsensical result type:
scala> simpleRec(List.empty[List[Int]])
res3: Option[B] = None
scala> simpleRec(List(List(1)))
res4: Option[B] = Some(Some(1))
How can I make this give me values of Option[Option[Int]] rather than Option[B]? I expect I'm making some silly mistake here, but can't work out what it is.
This probably was a bug, the following code works as expected:
object simpleRec extends Poly1 {
implicit def caseInt = at[Int](identity)
implicit def caseList[A](implicit ev: simpleRec.Case[A]) =
at[List[A]](_.headOption.map(simpleRec))
}
Using shapeless_2.11-2.0.0
I have the following use case which occurs often in my code:
A Collection[A]
An implicit conversion A to B
and I want to obtain a collection of B. I can use implicitly like the following:
case class Items(underlying:List[B])
import B._
def apply(a:List[A]):Items = {
val listOfB= a.map {implicitly[A=>B]}
Items(listOfB)
}
What is the most elegant way to do that in Scala, maybe with the help of Scalaz of doing the same?
Edit: the goal of my question is to find an idiomatic way, a common approach among libraries/developers. In such a sense developing my own pimp-my-library solution is something I dislike, because other people writing my code would not know the existence of this conversion and would not use it, and they will rewrite their own. I favour using a library approach for this common functions and that's why I am wondering whether in Scalaz it exists such a feature.
It's pretty straightforward if you know the types. First implicit conversion from A to B:
implicit def conversion(a: A): B = //...
then you need implicit conversion from List[S] to List[T] where S and T are arbitrary types for which implicit conversion from S to T exists:
implicit def convList[S, T](input: List[S])(implicit c: S => T): List[T] =
input map c
This should then work:
val listOfA: List[A] = //...
val listOfB: List[B] = listOfA
which is resolved by the compiler to:
val listOfB: List[B] = convList(listOfA)(conversion)
where S is A and T is B.
I wouldn't use an implicit conversion here, but a view bound in the class:
case class Foo(x: Int)
case class Bar(y: Int)
implicit def foo2Bar(foo: Foo) = Bar(foo.x)
case class Items[A <% Bar](xs: List[A]) {
def apply(x: Int): Bar = xs(x)
}
You can now create an instance of Items with a list of Foo and internally use them, as if they were Bars.
scala> Items(List(Foo(1)))
res8: Items[Foo] = Items(List(Foo(1)))
scala> res8(0)
res9: Bar = Bar(1)
edit:
Some clarification, on why I would not use an implicit conversion:
Implicit conversions can be dangerous, when they are in scope and accidentally convert things, that they shouldn't convert. I would always convert stuff explicitly or via view bounds, because then I can control it, also implicit conversion may shrink the size of your code, but also makes it harder to understand for others. I would only use implicit conversion for the 'extend my library' pattern.
edit2:
You could however add a method to the collection types, that does this conversion, if such a method is in scope:
trait Convertable[M[A], A] {
def convertTo[B](implicit f: A => B): M[B]
}
implicit def list2Convertable[A](xs: List[A]) = new Convertable[List, A] {
def convertTo[B](implicit f: A => B) = xs.map(f)
}
scala> implicit def int2String(x: Int) = x.toString
int2String: (x: Int)String
scala> List(1,2,3).convertTo[String]
res0: List[String] = List(1, 2, 3)
Instead of using another implicit conversion here, I would probably use a typeclass instead, but I think you get the basic idea.
Works starting with Scala 2.10:
implicit class ListOf[A](val list: List[A]) {
def of[B](implicit f: A => B): List[B] = list map f
}
implicit def int2String(i: Int) = i.toString
// Usage
List(1,2,3).of[String]
In my code, I'm using a more general version adapted from Tomasz' solution above which handles all Traversable instances
/** Implicit conversion for Traversable instances where the elements are convertable */
implicit def convTrav[S, T, I[S] <: Traversable[S]](input: I[S])(implicit c: S => T): I[T] =
(input map c).asInstanceOf[I[T]]
(This is working for me, although I'm keen to know if any more experienced Scala programmers think this is a bad idea for any reason, apart from the usual caveats about implicit conversions)