I have a function get: T => scala.concurrent.Future[T]
I want to iterates it like :
val futs: Iterator[Future[T]] = Iterator.iterate(get(init)){
_.flatMap(prev => get(prev))
}
But the type of Iterator is Future[T], it is not easy to process this iterator.
How could I transfer that to Process[?, T]
(Maybe T => Future[T] as context type F).
Not super nice solution, but works
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future => SFuture}
import scala.language.implicitConversions
import scalaz.concurrent.Task
import scalaz.stream._
implicit class Transformer[+T](fut: => SFuture[T]) {
def toTask(implicit ec: scala.concurrent.ExecutionContext): Task[T] = {
import scala.util.{Success, Failure}
import scalaz.syntax.either._
Task.async {
register =>
fut.onComplete {
case Success(v) => register(v.right)
case Failure(ex) => register(ex.left)
}
}
}
}
val init: Int = 0
def f(i: Int): SFuture[Int] = SFuture(i + 1)
val p = Process.repeatEval[Task, Int] {
var prev = init
f(prev).toTask.map(next => {prev = next; next})
}
println(p.take(10).runLog.run)
Assuming you know how to convert Future -> Task (either via implicit or via Process.transform) this shall work:
def get(t:T): Task[T] = ???
val initial : T = ???
val signal = scalaz.stream.async.signal[T]
// emit initial value, and follow by any change of `T` within the signal
val source:Process[Task,T] = eval_(signal.set(t)) fby signal.discrete
// sink to update `T` within the signal
val signalSink:Sink[Task,T] = constant((t:T) => signal.set(t))
// result, that esentially converts T => Task[T] into Process[Task,T]
val result: Process[Task,T] = source.observe(signalSink)
Finally I got what Pavel Chlupacek wanted to say. Signal looks cool, but a little bit cryptic for beginner.
import scala.concurrent.{Future => SFuture}
import scala.language.implicitConversions
import scalaz.concurrent.Task
import scalaz.stream._
import scala.concurrent.ExecutionContext.Implicits.global
implicit class Transformer[+T](fut: => SFuture[T]) {
def toTask(implicit ec: scala.concurrent.ExecutionContext): Task[T] = {
import scala.util.{Failure, Success}
import scalaz.syntax.either._
Task.async {
register =>
fut.onComplete {
case Success(v) => register(v.right)
case Failure(ex) => register(ex.left)
}
}
}
}
val init: Int = 0
def f(i: Int): SFuture[Int] = SFuture(i + 1)
val signal = scalaz.stream.async.signal[Int]
// Observe value and push them to signal
val signalSink: Process[Task, Int => Task[Unit]] = // =:= Sink[Task, Int]
Process.constant((input: Int) => signal.set(input))
// Start from init and then consume from signal
val result = (Process.eval(f(init).toTask) ++ signal.discrete.evalMap(i => f(i).toTask)) observe signalSink
println(result.take(10).runLog.run)
I made another solution
def iterate[F[_],A](init: A)(f: A => F[A]): Process[F, A] = {
Process.emit(init) ++ Process.await(f(init)) { next => iterate(next)(f)}
}
This is already an feature of scalaz-stream 0.6, see this pr for detail
Inorder to use scala.concurrent.Future as context type F
We need import scalaz.std.scalaFuture._ and an Catchable instance
implicit def futureCatchable(implicit ctx: ExecCtx): Catchable[Future] = {
new Catchable[Future] {
def attempt[A](f: Future[A]) = f.map(\/-(_)).recover { case e => -\/(e)}
def fail[A](err: Throwable) = Future.failed(err)
}
}
Finally I got this:
package stream
import scala.concurrent._
import scalaz._
import scalaz.stream._
package object future {
type ExecCtx = ExecutionContext
def iterate[F[_],A](init: A)(f: A => F[A]): Process[F, A] = {
Process.emit(init) ++ Process.await(f(init)) { next => iterate(next)(f)}
}
implicit def futureCatchable(implicit ctx: ExecCtx): Catchable[Future] = {
new Catchable[Future] {
def attempt[A](f: Future[A]) = f.map(\/-(_)).recover { case e => -\/(e)}
def fail[A](err: Throwable) = Future.failed(err)
}
}
}
object futureApp extends App {
import scalaz.Scalaz._
import future._
import scala.concurrent.ExecutionContext.Implicits.global
def get(i: Int) = Future {
println(i + 1)
i + 1
}
iterate(0)(get).takeWhile(_ < 100000).run
}
Related
Aloha! :)
I'm not happy about running all the time to the stackoverflow forums to get some help with another piece of strangeness scala/cats has thrown at me.
Problem is: There seems to be no really useful documentation, only some worthless - at least for me - repl lines.
Could please somebody of you point to some useful documentation? Some real code? Not just lines in the repl?
Here I just tried to work with scala/cats Eq and Show typeclasses...
What the hell am I doing wrong?
The class:
package org.hudelundpfusch.utilites.decisions.data
import cats.Show
import cats.kernel.Eq
case class Fact[+T <: Any](name: String, value: T)
extends Equals {
override def canEqual(that: Any): Boolean = that match {
case _: Fact[_] => true
case _ => false
}
override def equals(other: Any): Boolean = other match {
case that: Fact[_] =>
(that canEqual this) &&
name == that.name &&
value == that.value
case _ => false
}
override def hashCode(): Int = {
val state = Seq(name, value)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
}
override def toString = s"Fact(name=$name, value=$value)"
}
case object Fact {
implicit val factEq: Eq[Fact[_]] = Eq.fromUniversalEquals[Fact[_]] // Neither of this works
// implicit def factEq: Eq[Fact[_]] = new Eq[Fact[_]] {
// def eqv(x: Fact[_], y: Fact[_]): Boolean = (x != null, y != null) match {
// case (true, _) => x.equals(y)
// case (_, true) => y.equals(x)
// case _ => true
// }
// }
implicit def factShow[T]: Show[Fact[T]] = (t: Fact[T]) => t.toString // Example calls for 'implicit val factShow[Fact[_]]' but that doesn't work
}
And the big surprise:
package org.hudelundpfusch.utilites.decisions
import cats._
import cats.data._
import cats.syntax._
import cats.implicits._
import cats.implicits.eq
import com.typesafe.scalalogging.LazyLogging
import org.hudelundpfusch.utilites.decisions.data.Fact
import org.hudelundpfusch.utilites.decisions.data.Fact._
// Tried to import everything that came to my mind to make the stuff working
object Fuddel
extends App
with LazyLogging {
logger.info("Let's start to fuddel!")
this.fuddel()
logger.info("Enough with fuddling!")
def fuddel(): Unit = {
val fact1: Fact[String] = Fact[String]("FactName", "FactValue")
println(s"${fact1.show}")
val fact2: Fact[String] = Fact[String]("FactName", "FactValue")
println(s"${fact2.show}")
println(s"${fact1.equals(fact2)}")
println(s"${fact1 == fact2}")
// println(s"${fact1 === fact2}") // Not resolved...According to the repl example this should work with implicits imported
println(s"${fact1 eq fact2}") // False? Oh joy! Thanks to the great repl example!
}
}
So please, is there any documentation not beeing worthless?
Thanks in advance
Have a better day than me
Alex
1. This here compiles just fine (I removed your package name and logging dependency):
import cats.Show
import cats.kernel.Eq
case class Fact[+T](name: String, value: T) extends Equals {
override def canEqual(that: Any): Boolean = that match {
case _: Fact[_] => true
case _ => false
}
override def equals(other: Any): Boolean = other match {
case that: Fact[_] => true // TODO: replaced, irrelevant
case _ => false
}
override def hashCode(): Int = {
val state = Seq(name, value)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
}
override def toString = s"Fact(name=$name, value=$value)"
}
case object Fact {
implicit def factEq[A]: Eq[Fact[A]] = Eq.fromUniversalEquals[Fact[A]]
implicit def factShow[T]: Show[Fact[T]] = (t: Fact[T]) => t.toString
}
Note the universal quantification instead of wildcard in factEq[A]. Then in Fuddel.scala:
import cats.syntax.show._
import cats.syntax.eq._
import Fact._
object Fuddel
extends App {
this.fuddel()
def fuddel(): Unit = {
val fact1: Fact[String] = Fact[String]("FactName", "FactValue")
println(s"${fact1.show}")
val fact2: Fact[String] = Fact[String]("FactName", "FactValue")
println(s"${fact2.show}")
println(s"${fact1.equals(fact2)}")
println(s"${fact1 == fact2}")
println(s"${fact1 === fact2}")
println(s"${fact1 eq fact2}")// must be false, different instances
}
}
Note that the eq is a method that is available on every object in Scala, there is no way to override it.
2. I'd recommend to read Welsh, Gurnell "Scala with Cats". Scaladoc is good too, but you cannot navigate it effectively until you read the introductory chapter about the organization of packages and implicits in the cats library.
Is it possible to create stream of discrete events in fs2? if so how to do it.
I just started to play with the library and I know I have a lot to study. But I am not seeing any example related. e.g. I would like to create a stream for "mousemove" or "click" in scalajs or swing.
I am looking for something like in RxJS that I can use a Rx.Observable.create to create discrete events something like:
//note: pseudo code
var mouse = Rx.Observable.create( subscriber => {
document.body.addEventListener("mousemove", event =>{
subscriber.onNext(event)
})
} )
The equivalent in fs2 might not be so trivial but if anyone can suggest me how. I guess it would be using Handler and Pull/Push datatypes but I am far to understand how.
Cheers.
Here's an example I came up with which demonstrates how to use fs2 with JavaFX:
import cats.implicits._
import cats.effect._
import cats.effect.implicits._
import javafx.application.{Application, Platform}
import javafx.scene.{Node, Scene}
import javafx.scene.layout._
import javafx.stage.Stage
import fs2._
import fs2.concurrent._
import javafx.beans.value.WritableValue
import javafx.scene.control.{Label, TextField}
import javafx.scene.input.KeyEvent
import scala.concurrent.ExecutionContext
import scala.util.Try
class Fs2Ui extends Application {
override def start(primaryStage: Stage): Unit = {
implicit val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global)
implicit val timer: Timer[IO] = IO.timer(ExecutionContext.global)
new Logic[IO]().run(primaryStage).start.unsafeRunSync()
}
class Logic[F[_]: ConcurrentEffect: ContextShift: Timer] {
import Fs2Ui._
import java.time.{Duration, Instant}
import java.util.concurrent.TimeUnit.MILLISECONDS
def run(primaryStage: Stage): F[Unit] = for {
v <- initializeUi(primaryStage)
View(input, feedback) = v
_ <- Stream(input).covary[F]
.through(typedChars)
.through(processInput)
.through(displayFeedback(feedback.textProperty))
.compile.drain
} yield ()
private def initializeUi(primaryStage: Stage): F[View] = updateUi {
val input = new TextField()
input.setPrefWidth(300)
val feedback = new Label("...")
val vbox = new VBox(input, feedback)
val root = new StackPane(vbox)
val scene = new Scene(root)
primaryStage.setScene(scene)
primaryStage.show()
View(input, feedback)
}
private def processInput: Pipe[F, TypedChar, Feedback] = for {
typed <- _
_ <- Stream.eval(ContextShift[F].shift)
res <- Stream.eval { time(processSingle(typed)) }
(d, Feedback(str)) = res
} yield Feedback(s"$str in [$d]")
private def displayFeedback(value: WritableValue[String]): Pipe[F, Feedback, Unit] =
_.map { case Feedback(str) => str } through updateValue(value)
private def time[A](f: F[A]): F[(Duration, A)] = {
val now = Timer[F].clock.monotonic(MILLISECONDS).map(Instant.ofEpochMilli)
for {
start <- now
a <- f
stop <- now
d = Duration.between(start, stop)
} yield (d, a)
}
private val processSingle: TypedChar => F[Feedback] = {
import scala.util.Random
import scala.concurrent.duration._
val prng = new Random()
def randomDelay: F[Unit] = Timer[F].sleep { (250 + prng.nextInt(750)).millis }
c => randomDelay *> Sync[F].delay(Feedback(s"processed $c"))
}
}
}
object Fs2Ui {
case class View(input: TextField, feedback: Label)
case class TypedChar(value: String)
case class Feedback(value: String)
private def typedChars[F[_]: ConcurrentEffect]: Pipe[F, Node, TypedChar] = for {
node <- _
q <- Stream.eval(Queue.unbounded[F, KeyEvent])
_ <- Stream.eval(Sync[F].delay {
node.setOnKeyTyped { evt => (q enqueue1 evt).toIO.unsafeRunSync() }
})
keyEvent <- q.dequeue
} yield TypedChar(keyEvent.getCharacter)
private def updateValue[F[_]: Async, A](value: WritableValue[A]): Pipe[F, A, Unit] = for {
a <- _
_ <- Stream.eval(updateUi(value setValue a))
} yield ()
private def updateUi[F[_]: Async, A](action: => A): F[A] =
Async[F].async[A] { cb =>
Platform.runLater { () =>
cb(Try(action).toEither)
}
}
}
The specific parts that demonstrate bindings between fs2 and JavaFX are the two Pipes: typedChars and updateValue. Personally, I think, the most challenging part was adapting a KeyEvent listener to look like an fs2 Stream of events:
node.setOnKeyTyped { evt => (q enqueue1 evt).toIO.unsafeRunSync() }
Scala version: 2.11.8
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.mvc._
object foooo {
type ActionFilter[R] = R => Future[Either[Int, Unit]]
case class FooRequest[A](request: Request[A]) extends WrappedRequest(request)
implicit class ActionFilterOps[R](val f: ActionFilter[R]) {
def * (f1: ActionFilter[R]): ActionFilter[R] = { (r: R) =>
f(r).flatMap {
case Left(r) => Future.successful(Left(r))
case Right(_) => f1(r)
}
}
}
def test[A]() = {
val f0: ActionFilter[FooRequest[A]] = { (r: FooRequest[A]) =>
Future.successful(Left(1))
}
val f1 = f0
ActionFilterOps(f1) * f0 // Ok
f1 * f0 // Won't compile
}
}
As you can see, implicit class not work. I have to new the ActionFilterOps
As a side note: it helps if you have a self contained example that does not depend on external dependencies (such as Play) if that is possible.
Now onto the answer, or at least fix of the error... If you change the type alias ActionFilter to a class that wraps a function it works.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
case class ActionFilter[R](f: R => Future[Either[Int, Unit]]) { def apply(r: R) = f(r) }
type Request[A] = Option[A]
case class FooRequest[A](request: Request[A])
implicit class ActionFilterOps[R](val f: ActionFilter[R]) {
def * (f1: ActionFilter[R]): ActionFilter[R] = ActionFilter{ (r: R) =>
f(r).flatMap {
case Left(r) => Future.successful(Left(r))
case Right(_) => f1(r)
}
}
}
def test[A]() = {
val f0: ActionFilter[FooRequest[A]] = ActionFilter{ (r: FooRequest[A]) =>
Future.successful(Left(1))
}
val f1 = f0
ActionFilterOps(f1) * f0 // Ok
f1 * f0 // Ok
}
It also works if you use the raw function type instead of the type alias.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
type Request[A] = Option[A]
case class FooRequest[A](request: Request[A])
implicit class ActionFilterOps[R](val f: R => Future[Either[Int, Unit]]) {
def * (f1: R => Future[Either[Int, Unit]]): R => Future[Either[Int, Unit]] = { (r: R) =>
f(r).flatMap {
case Left(r) => Future.successful(Left(r))
case Right(_) => f1(r)
}
}
}
def test[A]() = {
val f0: FooRequest[A] => Future[Either[Int, Unit]] = { (r: FooRequest[A]) =>
Future.successful(Left(1))
}
val f1 = f0
ActionFilterOps(f1) * f0 // Ok
f1 * f0 // Ok
}
Especially that second "solution" makes me think that this is a bug.
I have this class that manage reception of a stream of asynchronous messages. It has type argument, say A, and I like to implement a function that filter those messages by type, say B<:A
But my first implementation is not working due to type erasure (see example below). Is there a good way to so?
Here is a simplified example of my problem:
package test.filterByType
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.Future
trait MessageStream[A]{ self =>
def next(): Future[A]
def filter[B<:A]: MessageStream[B] = new MessageStream[B]{
def next(): Future[B] = self.next.flatMap{
case b: B => Future.successful(b)
case _ => next()
}
}
}
case class MessageStreamImpl[A](msg: IndexedSeq[A]) extends MessageStream[A]{
private var index = 0
def next() = {
index += 1
Future.successful(msg(index-1))
}
}
object Main{
trait A
case class B(i: Int) extends A
case class C(i: Int) extends A
def main(args: Array[String]){
val msg: IndexedSeq[A] = (1 to 10).map{ i => if(i%2==0) B(i) else C(i) }
val streamOfA = MessageStreamImpl(msg)
val streamOfB = streamOfA.filter[B]
val b: B = Await.result(streamOfB.next(), 1 second)
}
}
At compilation, I get warning: abstract type pattern B is unchecked since it is eliminated by erasure, and indeed the code does not work. If I execute Main, I get the error:
lang.ClassCastException: test.filterByType.Main$C cannot be cast to test.filterByType.Main$B
Which happens because it does not filter out the first list item C(1)
This small adjustment does the trick
import scala.reflect.ClassTag
def filter[B<:A](implicit C: ClassTag[B]): MessageStream[B] = new MessageStream[B]{
def next(): Future[B] = self.next.flatMap{
case b: B => Future.successful(b)
case _ => next()
}
}
I've found an alternative that works:
def collect[B<:A](f: PartialFunction[A,B]) = new MessageStream[B] {
override def next(): Future[B] = self.next().flatMap { m =>
if (f.isDefinedAt(m)) Future.successful(f(m))
else next()
}
}
Inspired by travisbrown, I'm trying to use a macro to create some "smart constructors".
Given
package mypkg
sealed trait Hello[A]
case class Ohayo[A,B](a: (A,B)) extends Hello[A]
and
val smartConstructors = FreeMacros.liftConstructors[Hello]
The macro should find all the subclasses of Hello, look at their constructors, and extract a few elements to populate this tree for the "smart constructor":
q"""
def $methodName[..$typeParams](...$paramLists): $baseType =
$companionSymbol[..$typeArgs](...$argLists)
"""
I hoped to get:
val smartConstructors = new {
def ohayo[A, B](a: (A, B)): Hello[A] = Ohayo[A, B](a)
}
but instead get:
error: type mismatch;
found : (A(in class Ohayo), B(in class Ohayo))
required: ((some other)A(in class Ohayo), (some other)B(in class Ohayo))
val liftedConstructors = FreeMacros.liftConstructors[Hello]
At a glance, the tree looks ok to me:
scala> q" new { ..$wellTyped }"
res1: u.Tree =
{
final class $anon extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
def ohayo[A, B](a: (A, B)): net.arya.constructors.Hello[A] = Ohayo[A, B](a)
};
new $anon()
}
but I guess it invisibly isn't. If I naively try to freshen up the typeParams with info.typeParams.map(p => TypeName(p.name.toString)), I get "can't splice A as type parameter" when I do the quasiquoting.
Where am I going wrong? Thanks for taking a look.
-Arya
import scala.language.experimental.macros
import scala.reflect.api.Universe
import scala.reflect.macros.whitebox
class FreeMacros(val c: whitebox.Context) {
import c.universe._
import FreeMacros._
def liftedImpl[F[_]](implicit t: c.WeakTypeTag[F[_]]): Tree = {
val atc = t.tpe
val childSymbols: Set[ClassSymbol] = subCaseClassSymbols(c.universe)(atc.typeSymbol.asClass)
val wellTyped = childSymbols.map(ctorsForSymbol(c.universe)(atc)).unzip
q"new { ..${wellTyped} }"
}
}
object FreeMacros {
def liftConstructors[F[_]]: Any = macro FreeMacros.liftedImpl[F]
def smartName(name: String): String = (
name.toList match {
case h :: t => h.toLower :: t
case Nil => Nil
}
).mkString
def subCaseClassSymbols(u: Universe)(root: u.ClassSymbol): Set[u.ClassSymbol] = {
val subclasses = root.knownDirectSubclasses
val cast = subclasses.map(_.asInstanceOf[u.ClassSymbol])
val partitioned = mapped.partition(_.isCaseClass)
partitioned match {
case (caseClasses, regularClasses) => caseClasses ++ regularClasses.flatMap(r => subCaseClassSymbols(u)(r))
}
}
def ctorsForSymbol(u: Universe)(atc: u.Type)(caseClass: u.ClassSymbol): (u.DefDef, u.DefDef) = {
import u._
import internal._
// these didn't help
// def clearTypeSymbol(s: Symbol): TypeSymbol = internal.newTypeSymbol(NoSymbol, s.name.toTypeName, s.pos, if(s.isImplicit)Flag.IMPLICIT else NoFlags)
// def clearTypeSymbol2(s: Symbol): TypeSymbol = internal.newTypeSymbol(NoSymbol, s.name.toTypeName, NoPosition, if(s.isImplicit)Flag.IMPLICIT else NoFlags)
// def clearTypeDef(d: TypeDef): TypeDef = internal.typeDef(clearTypeSymbol(d.symbol))
val companionSymbol: Symbol = caseClass.companion
val info: Type = caseClass.info
val primaryCtor: Symbol = caseClass.primaryConstructor
val method = primaryCtor.asMethod
val typeParams = info.typeParams.map(internal.typeDef(_))
// val typeParams = info.typeParams.map(s => typeDef(newTypeSymbol(NoSymbol, s.name.toTypeName, NoPosition, NoFlags)))
// val typeParams = info.typeParams.map(s => internal.typeDef(clearTypeSymbol2(s)))
val typeArgs = info.typeParams.map(_.name)
val paramLists = method.paramLists.map(_.map(internal.valDef(_)))
val argLists = method.paramLists.map(_.map(_.asTerm.name))
val baseType = info.baseType(atc.typeSymbol)
val List(returnType) = baseType.typeArgs
val methodName = TermName(smartName(caseClass.name.toString))
val wellTyped =
q"""
def $methodName[..$typeParams](...$paramLists): $baseType =
$companionSymbol[..$typeArgs](...$argLists)
"""
wellTyped
}
}
P.S. I have been experimenting with toolbox.untypecheck / typecheck per this article but haven't found a working combination.
you need using
clas.typeArgs.map(_.toString).map(name => {
TypeDef(Modifiers(Flag.PARAM),TypeName(name), List(),TypeBoundsTree(EmptyTree, EmptyTree))
}
replace
info.typeParams.map(p => TypeName(p.name.toString))
it si my code
object GetSealedSubClass {
def ol3[T]: Any = macro GetSealedSubClassImpl.ol3[T]
}
class GetSealedSubClassImpl(val c: Context) {
import c.universe._
def showInfo(s: String) =
c.info(c.enclosingPosition, s.split("\n").mkString("\n |---macro info---\n |", "\n |", ""), true)
def ol3[T: c.WeakTypeTag]: c.universe.Tree = {
//get all sub class
val subClass = c.weakTypeOf[T]
.typeSymbol.asClass.knownDirectSubclasses
.map(e => e.asClass.toType)
//check type params must ia s sealed class
if (subClass.size < 1)
c.abort(c.enclosingPosition, s"${c.weakTypeOf[T]} is not a sealed class")
// get sub class constructor params
val subConstructorParams = subClass.map { e =>
//get constructor
e.members.filter(_.isConstructor)
//if the class has many Constructor then you need filter the main Constructor
.head.map(s => s.asMethod)
//get function param list
}.map(_.asMethod.paramLists.head)
.map(_.map(e => q"""${e.name.toTermName}:${e.info} """))
val outfunc = subClass zip subConstructorParams map {
case (clas, parm) =>
q"def smartConstructors[..${
clas.typeArgs.map(_.toString).map(name => {
TypeDef(Modifiers(Flag.PARAM), TypeName(name), List(), TypeBoundsTree(EmptyTree, EmptyTree))
})
}](..${parm})=${clas.typeSymbol.name.toTermName} (..${parm})"
}
val outClass =
q"""
object Term{
..${outfunc}
}
"""
showInfo(show(outClass))
q"""{
$outClass
Term
}
"""
}
}
using like this
sealed trait Hello[A]
case class Ohayo[A, B](a: (A, B)) extends Hello[A]
object GetSealed extends App {
val a = GetSealedSubClass.ol3[Hello[_]]
val b=a.asInstanceOf[ {def smartConstructors[A, B](a: (A, B)): Ohayo[A, B]}].smartConstructors(1, 2).a
println(b)
}