In this snippet y.run doesn't typecheck.
object Test {
type StateStringTask[A] = StateStringT[Task, A]
type StateStringT[M[_], A] = StateT[M, String, A]
val x: Process[Task, Unit] = ???
val y: Process[StateStringTask, Unit] = ???
x.run // This typechecks
y.run // This fails
}
The compiler shows this error:
could not find implicit value for parameter C: scalaz.Catchable[[x]Test.StateStringTask[x]]
Do I have to create a Catchable instance for StateStringTask? How do I do that? Or is there an easier way to handle stateful effects when running a Process?
I guess this is suboptimal but I got it by making StateStringTask an instance of Catchable:
implicit val stateStringTaskInstance: Catchable[StateStringTask] =
new Catchable[StateStringTask] {
// `a.attempt` stackoverflows, don't ask me why :)
def attempt[A](a: StateStringTask[A]): StateStringTask[Throwable \/ A] = a >>= (
x => Catchable[Task].attempt(Applicative[Task].pure(x)).liftM[StateStringT]
)
def fail[A](err: Throwable) = Catchable[Task].fail(err).liftM[StateStringT]
}
To hoist the StateT on a Process with aTask as effect. For example:
def received(queue: Queue[Event]): Process[StateStringTask, Event] = {
val toStateStringTask = new (Task ~> StateStringTask) {
def apply[A](t: Task[A]): StateStringTask[A] = t.liftM[StateStringT]
}
// queue.dequeue: Process[Task, Event]
queue.dequeue.translate(toStateStringTask)
}
Related
Suppose we have a generic type (for example, Seq[E]) and a concrete subtype (for example, Seq[Int]). How can we extract concrete type that corresponds to the type parameters of the abstraction type. In other words, how can we know E -> Int.
Below is a minimal code example that tests for the desired behavior. The extractTypeBinding function would perform the transformation in question.
import scala.reflect.runtime.{universe => ru}
class MyFuncs
object MyFuncs {
def fn1[E](s: Seq[E]): E = ???
def fn2[K, V](m: Map[K, V]): Int = ???
}
object Scratch {
def extractTypeBinding(genType: ru.Type, typeParam: ru.Type)(concreteType: ru.Type): ru.Type = ???
def getArgTypes(methodSymbol: ru.MethodSymbol): Seq[ru.Type] =
methodSymbol.paramLists.headOption.getOrElse(Nil).map(_.typeSignature)
def main(a: Array[String]): Unit = {
// Grab the argument types of our methods.
val funcsType = ru.typeOf[MyFuncs].companion
val fn1ArgTypes = getArgTypes(funcsType.member(ru.TermName("fn1")).asMethod)
val fn2ArgTypes = getArgTypes(funcsType.member(ru.TermName("fn2")).asMethod)
val genericSeq = fn1ArgTypes.head // Seq[E]
val genericMap = fn2ArgTypes.head // Map[K, V]
// Create an extractor for the `E` in `Seq[E]`.
val seqElExtractor = extractTypeBinding(genericSeq, genericSeq.typeArgs.head) _
// Extractor for the `K` in `Map[K,V]`
val mapKeyExtractor = extractTypeBinding(genericMap, genericMap.typeArgs.head) _
// Extractor for the `V` in `Map[K,V]`
val mapValueExtractor = extractTypeBinding(genericMap, genericMap.typeArgs(1)) _
println(seqElExtractor(ru.typeOf[Seq[Int]])) // should be Int
println(seqElExtractor(ru.typeOf[Seq[Map[String, Double]]])) // should be Map[String, Double]
println(mapKeyExtractor(ru.typeOf[Map[String, Double]])) // should be String
println(mapKeyExtractor(ru.typeOf[Map[Int, Boolean]])) // should be Int
println(mapValueExtractor(ru.typeOf[Map[String, Double]])) // should be Double
println(mapValueExtractor(ru.typeOf[Map[Int, Boolean]])) // should be Boolean
}
}
Based on the docstrings, it seems like asSeenFrom should be the key to implementing extractTypeBinding. I tried the below implementation, but it returned the type parameter unchanged.
def extractTypeBinding(genType: ru.Type, typeParam: ru.Type)(concreteType: ru.Type): ru.Type =
typeParam.asSeenFrom(concreteType, genType.typeSymbol.asClass)
...
println(seqElExtractor(ru.typeOf[Seq[Int]])) // E
println(seqElExtractor(ru.typeOf[Seq[Map[String, Double]]])) // E
If asSeenFrom is the correct approach, what would the correct incantation be?
If not, then how should this be done?
The simplest solution came from the helpful prodding by Dmytro Mitin in the comments.
I had a couple misunderstandings about .typeArgs that were cleared up with some additional experimentation.
It returns all type arguments, not just the abstract ones.
It only returns the "top level" type arguments of the type you call it on. In other words, Map[A, Map[B, C]] only has 2 type args (A and Map[B, C])
Both of those seem very intuitive now, but I initially made some foolish assumptions. Below is a modified version of my test that more clearly achieves my original intent.
class MyFuncs
object MyFuncs {
def fn1[E](s: Seq[E]): E = ???
def fn2[K, V](m: Map[K, V]): Int = ???
}
object Scratch {
def typeArgBindings(genericType: ru.Type, concreteType: ru.Type): Map[ru.Type, ru.Type] =
// #todo consider validating both have the same base type.
genericType.typeArgs.zip(concreteType.typeArgs).toMap
def getArgTypes(methodSymbol: ru.MethodSymbol): Seq[ru.Type] =
methodSymbol.paramLists.headOption.getOrElse(Nil).map(_.typeSignature)
def main(a: Array[String]): Unit = {
// Grab the argument types of our methods.
val funcsType = ru.typeOf[MyFuncs].companion
val fn1ArgTypes = getArgTypes(funcsType.member(ru.TermName("fn1")).asMethod)
val fn2ArgTypes = getArgTypes(funcsType.member(ru.TermName("fn2")).asMethod)
val genericSeq = fn1ArgTypes.head // Seq[E]
val genericMap = fn2ArgTypes.head // Map[K, V]
println(typeArgBindings(genericSeq, ru.typeOf[Seq[Int]])) // Map(E -> Int)
println(typeArgBindings(genericSeq, ru.typeOf[Seq[Map[String, Double]]])) // Map(E -> Map[String,Double])
println(typeArgBindings(genericMap, ru.typeOf[Map[String, Double]])) // Map(K -> String, V -> Double)
println(typeArgBindings(genericMap, ru.typeOf[Map[Int, Boolean]])) // Map(K -> Int, V -> Boolean)
}
}
In the code below I'm using cats' EitherT class. It compiles, but I was forced to use the Error trait in:
def isNeg(i:Int): Future[Either[Error,Int]] = Future {
where my intent was to declare the function as:
def isNeg(i:Int): Future[Either[IsPositive,Int]] = Future {
but if I use IsPositive (the class returned in the function's Left) Scala throws a compilation error. Why doesn't it compile with IsPositive ?
import cats.data.EitherT
import cats.implicits._
trait Error
case class IsNegative() extends Error
case class IsPositive() extends Error
object HelloScala extends App {
def isPos(i:Int): Future[Either[IsNegative,Int]] = Future {
if (i>0)
Right(i)
else
Left(IsNegative())
}
def isNeg(i:Int): Future[Either[Error,Int]] = Future {
if (i<0)
Right(i)
else
Left(IsPositive())
}
def myFunction (i: Int) = {
val result = for {
ret <- EitherT(isPos(i)) // <-- compilation error, if IsPositive is used in isNeg
ret2 <- EitherT(isNeg(ret))
} yield ret2
println(result.value)
}
}
How does yield works? It is translated to flatMap (see here). So, let's try to rewrite your case with flatMap and with explicit types for non-compilable version:
val eithert1: EitherT[Future, IsNegative, Int] = EitherT(isPos(i))
def eithert2(ret: Int): EitherT[Future, IsPositive, Int] = EitherT(isNeg(ret))
eithert1.flatMap(ret => eithert2(ret)).map(ret2 => ret2)
And now what types you have:
// What is expected (see `EitherT` type bounds in sources, I copied here)
// flatMap -> EitherT[F[_], A, B].flatMap[AA >: A, D](f: B => EitherT[F, AA, D])
// what you have:
// EitherT[Future, IsNegative, Int].flatMap[IsPositive >: IsNegative, Int](f: Int => EitherT[Future, IsPositive, Int])
You see: IsPositive >: IsNegative, which is wrong. Expected super-type for IsNegative (either Error or IsNegative)
Lets say I have
case class Sample(i:Int, b:Boolean)
and
Map[String, String]("i" => "1", "b" => "false")
What is most concise way to instantiate any case class(if all fields are in map), signature like this:
get[T](map:[String, String]) : T
Probably shapeless can help acomplish this task, but I am almost unfamiliar with it. Thanks!
Firstly you can transform Map[String, String] into Map[Symbol, Any] and then use type classes shapeless.ops.maps.FromMap (or extention method .toRecord) and LabelledGeneric:
import shapeless.LabelledGeneric
import shapeless.record.Record
import shapeless.syntax.std.maps._
case class Sample(i: Int, b: Boolean)
val rec = Map('i -> 1, 'b -> false).toRecord[Record.`'i -> Int, 'b -> Boolean`.T].get
LabelledGeneric[Sample].from(rec) //Sample(1,false)
If not using Shapeless is an option for you, you could do it in a simple way without it. Here is a sample implementation where I use the Try Monad and a pattern matching to transform the Map into your case class:
(Try("1".toInt), Try("false".toBoolean)) match {
case (Success(intVal), Success(boolVal)) =>
Sample(intVal, boolVal)
case _ => // Log and ignore the values
}
Of course this is a bit verbose than the Shapeless version, but if you do not want to use a full library just for this simple use case, you could always do it using Scala library!
guys. Probably I wasn't too concise. What I really need is Generic parser from Map of Strings to case class. Thanks for pointing out to LabelledGeneric. Here is solution:
import shapeless.labelled.{FieldType, field}
import shapeless.{::, HList, HNil, LabelledGeneric, Lazy, Witness}
object FieldParser {
trait ValParser[A] {
def parse(str:String): A
}
trait FieldParser[A] {
def parse: A
}
type FT[A, B] = FieldType[A, B]
type ListField[K <: Symbol, A] = FieldType[K, List[A]]
type FP[A] = FieldParser[A]
type Args = (List[String],Map[String, Int])
type Named[K <: Symbol] = Witness.Aux[K]
private def create[A](thunk: A): FP[A] = {
new FP[A] {
def parse: A = thunk
}
}
def apply[A](implicit st: Lazy[FP[A]]): FP[A] = st.value
implicit def genericParser[A, R <: HList](implicit generic: LabelledGeneric.Aux[A, R], parser: Lazy[FP[R]], args:Args): FP[A] = {
create(generic.from(parser.value.parse))
}
implicit def hlistParser[K <: Symbol, H, T <: HList](implicit hParser: Lazy[FP[FT[K, H]]], tParser: FP[T]): FP[FT[K, H] :: T] = {
create {
val hv = hParser.value.parse
val tv = tParser.parse
hv :: tv
}
}
implicit def standardTypeParser[K <: Symbol, V:ValParser](implicit named: Named[K], args:Args): FP[FieldType[K, V]] = {
create(field[K](implicitly[ValParser[V]].parse(findArg)))
}
implicit def optionParser[V](implicit valParser:ValParser[V]): ValParser[Option[V]] = new ValParser[Option[V]]{
def parse(str:String):Option[V] = {
str.isEmpty match {
case true => None
case false => Some(valParser.parse(str))
}
}
}
implicit def listParser[V](implicit valParser:ValParser[V]): ValParser[List[V]] = new ValParser[List[V]]{
def parse(str:String):List[V] = {
str.isEmpty match {
case true => Nil
case false => str.split(",").map(valParser.parse).toList
}
}
}
implicit def doubleParser: ValParser[Double] = new ValParser[Double]{
def parse(str:String):Double = str.toDouble
}
implicit def intParser: ValParser[Int] = new ValParser[Int]{
def parse(str:String):Int = str.toInt
}
implicit def strParser: ValParser[String] = new ValParser[String]{
def parse(str:String):String = str
}
implicit def boolParser: ValParser[Boolean] = new ValParser[Boolean]{
def parse(str:String):Boolean = str.toBoolean
}
implicit val hnilParser: FP[HNil] = create(HNil)
private def findArg[K <: Symbol](implicit args:Args, named: Named[K]): String = {
val name = named.value.name
val index = args._2(name)
args._1(index)
}
}
I have an idea (vague), to pass (or chain) some implicit value in this manner, not introducing parameters to block f:
def block(x: Int)(f: => Unit)(implicit v: Int) = {
implicit val nv = v + x
f
}
def fun(implicit v: Int) = println(v)
such that if I used something alike:
implicit val ii: Int = 0
block(1) {
block(2) {
fun
}
}
It would print 3.
If I could say def block(x: Int)(f: implicit Int => Unit).
In other words I'm seeking for some design pattern which will allow me to implement this DSL: access some cumulative value inside nested blocks but without explicitly passing it as parameter. Is it possible? (implicits are not necessary, just a hint to emphasize that I don't want to pass that accumulator explicitly). Of course upper code will print 0.
EDIT: One of possible usages: composing http routes, in a following manner
prefix("path") {
prefix("subpath") {
post("action1") { (req, res) => do action }
get("action2") { (req, res) => do action }
}
}
Here post and get will access (how?) accumulated prefix, say List("path", "subpath") or "/path/subpath/".
Consider using DynamicVariable for this. It's really simple to use, and thread-safe:
val acc: DynamicVariable[Int] = new DynamicVariable(0)
def block(x: Int)(f: => Unit) = {
acc.withValue(acc.value + x)(f)
}
def fun = println(acc.value)
Passing state via implicit is dirty and will lead to unexpected and hard to track down bugs. What you're asking to do is build a function that can compose in such a way that nested calls accumulate over some operation and anything else uses that value to execute the function?
case class StateAccum[S](init: S){
val op: S => S
def flatMap[A <: S](f: S => StateAccum[A]) ={
val StateAccum(out) = f(s)
StateAccum(op(init, out))
}
def apply(f: S => A) = f(init)
}
which could allow you do exactly what you're after with a slight change in how you're calling it.
Now, if you really want the nested control structures, your apply would have to use an implicit value to distinguish the types of the return such that it applied the function to one and a flatMap to StateAccum returns. It gets crazy but looks like the following:
def apply[A](f: S => A)(implicit mapper: Mapper[S, A]): mapper.Out = mapper(this, f)
trait Mapper[S, A]{
type Out
def apply(s: StateAccum[S], f: S => A): Out
}
object Mapper extends LowPriorityMapper{
implicit def acuum[S, A <: S] = new Mapper[S, StateAccum[A]]{
type Out = StateAccum[A]
def apply(s: StateAccum[S], f: S => StateAccum[A]) = s.flatMap(f)
}
}
trait LowPriorityMapper{
implicit def acuum[S, A] = new Mapper[S, A]{
type Out = A
def apply(s: StateAccum[S], f: S => A) = f(s.init)
}
}
I am trying to write some extension methods for the Scala collections, and running into trouble fully generifying them.
A first attempt at tailOption yields something like:
implicit class TailOption[A, Repr <: GenTraversableLike[A, Repr]](val repr: Repr) {
def tailOption: Option[Repr] =
if (repr.isEmpty) None
else Some(repr.tail)
}
unfortunately, this doesn't work:
scala> List(1,2,3).tailOption
<console>:19: error: value tailOption is not a member of List[Int]
List(1,2,3).tailOption
Scala 2.10 provides the IsTraversableLike type-class to help adapt this sort of thing for all collections (including odd ones, like Strings).
With this I can for instance implement tailOption quite easily:
implicit class TailOption[Repr](val r: Repr)(implicit fr: IsTraversableLike[Repr]) {
def tailOption: Option[Repr] = {
val repr = fr.conversion(r)
if (repr.isEmpty) None
else Some(repr.tail)
}
}
scala> List(1,2,3).tailOption
res12: Option[List[Int]] = Some(List(2, 3))
scala> "one".tailOption
res13: Option[String] = Some(ne)
The result is of the correct type: Option[<input-type>]. Specifically, I have been able to preserve the Repr type when calling methods that return Repr, like `tail.
Unfortunately, I can't seem to use this trick to preserve the type of the elements of the collection. I can't call methods that return an element.
IsTraversableLike does have a member A but it doesn't seem very useful. In particular I can't reconstruct my original element type and the member is not equivalent in type. For instance, without further work, headTailOption looks like this:
implicit class HeadTailOption[Repr](val r: Repr)(implicit val fr: IsTraversableLike[Repr]) {
def headTailOption: Option[(fr.A, Repr)] = {
val repr = fr.conversion(r)
if (repr.isEmpty) None
else Some(repr.head -> repr.tail)
}
}
scala> val Some((c, _)) = "one".headTailOption
c: _1.fr.A forSome { val _1: HeadTailOption[String] } = o
As we can see, c has a wonderfully baroque type. But, this type is not equivalent to Char:
scala> val fr = implicitly[IsTraversableLike[String]]
fr: scala.collection.generic.IsTraversableLike[String] = scala.collection.generic.IsTraversableLike$$anon$1#60ab6a84
scala> implicitly[fr.A <:< Char]
<console>:25: error: Cannot prove that fr.A <:< Char.
implicitly[fr.A <:< Char]
I have tried all sorts of tricks including having Repr[A] <: GenTraversableLike[A, Repr[A]] none of which help. Can anyone work out the magic sauce to make headTailOption return the right types for:
val headTailString: Option[(Char, String)] = "one".headTailOption
val headTailList: Option[(Int, List[Int])] = List(1,2,3).headTailOption
A partial answer. You have probably started from the scaladoc example for IsTraversableLike. It still uses the "old approach" of separating implicit conversion and instantiating the wrapper class, instead of going in one step through an implicit class. It turns out that the "old approach" does work:
import collection.GenTraversableLike
import collection.generic.IsTraversableLike
final class HeadTailOptionImpl[A, Repr](repr: GenTraversableLike[A, Repr]) {
def headTailOption: Option[(A, Repr)] = {
if (repr.isEmpty) None
else Some(repr.head -> repr.tail)
}
}
implicit def headTailOption[Repr](r: Repr)(implicit fr: IsTraversableLike[Repr]):
HeadTailOptionImpl[fr.A,Repr] = new HeadTailOptionImpl(fr.conversion(r))
// `c` looks still weird: `scala.collection.generic.IsTraversableLike.stringRepr.A`
val Some((c, _)) = "one".headTailOption
val d: Char = c // ...but it really is a `Char`!
val headTailString: Option[(Char, String)] = "one".headTailOption
val headTailList: Option[(Int, List[Int])] = List(1,2,3).headTailOption
As Miles points out, the split seems essential for this to work with the implicit search and type inference.
Another solution, although of course less elegant, is to give up the unification of strings and collections:
trait HeadTailOptionLike[A, Repr] {
def headTailOption: Option[(A, Repr)]
}
implicit class GenHeadTailOption[A, Repr](repr: GenTraversableLike[A, Repr])
extends HeadTailOptionLike[A, Repr] {
def headTailOption =
if (repr.isEmpty) None
else Some(repr.head -> repr.tail)
}
implicit class StringHeadTailOption(repr: String)
extends HeadTailOptionLike[Char, String] {
def headTailOption =
if (repr.isEmpty) None
else Some(repr.head -> repr.tail) // could use repr.charAt(0) -> repr.substring(1)
}
List(1,2,3).headTailOption
"one".headTailOption
You can write it as an implicit class if you extract the type A from the IsTraversableLike.
import collection.generic.IsTraversableLike
implicit class HeadTailOption[Repr,A0](val r: Repr)(implicit val fr: IsTraversableLike[Repr]{ type A = A0 }) {
def headTailOption: Option[(A0, Repr)] = {
val repr = fr.conversion(r)
if (repr.isEmpty) None
else Some(repr.head -> repr.tail)
}
}
Or equivalently:
import collection.generic.IsTraversableLike
type IsTraversableLikeAux[Repr,A0] = IsTraversableLike[Repr]{ type A = A0 }
implicit class HeadTailOption[Repr,A](val r: Repr)(implicit val fr: IsTraversableLikeAux[Repr,A]) {
def headTailOption: Option[(A, Repr)] = {
val repr = fr.conversion(r)
if (repr.isEmpty) None
else Some(repr.head -> repr.tail)
}
}
And then everything works fine.
scala> val Some((c, _)) = "one".headTailOption
c: scala.collection.generic.IsTraversableLike.stringRepr.A = o
scala> c.isSpaceChar
res0: Boolean = false
The compiler knows that scala.collection.generic.IsTraversableLike.stringRepr.A is the same as Char.