by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Aug 07 15:39
    codecov-commenter commented #153
  • Aug 07 15:39
    codecov-commenter commented #153
  • Aug 07 15:38
    joroKr21 assigned #153
  • Aug 07 15:38
    joroKr21 labeled #153
  • Aug 07 15:38
    joroKr21 review_requested #153
  • Aug 07 15:38
    joroKr21 review_requested #153
  • Aug 07 15:35
    joroKr21 edited #153
  • Aug 07 15:33
    joroKr21 ready_for_review #153
  • Aug 07 15:33
    codecov-commenter commented #153
  • Aug 07 15:33
    joroKr21 synchronize #153
  • Aug 07 15:24

    joroKr21 on master

    Add laws for Aspect and Instrum… (compare)

  • Aug 07 15:24
    joroKr21 closed #156
  • Aug 07 07:41

    joroKr21 on master

    Update scalacheck-1-14 to 3.2.1… (compare)

  • Aug 07 07:41
    joroKr21 closed #157
  • Aug 07 07:37
    codecov-commenter commented #157
  • Aug 07 07:31
    codecov-commenter commented #157
  • Aug 07 07:25
    scala-steward opened #157
  • Aug 06 19:17
    codecov-commenter commented #153
  • Aug 06 19:12
    codecov-commenter commented #153
  • Aug 06 19:05
    codecov-commenter commented #153
Soren
@srnb_gitlab
case class PinDefinition(
  dataType: PinType,
  direction: PinDirection,
  voxel: Position
)

sealed trait PinType
object PinType {

  case object Number extends PinType
  case object Object extends PinType
  case object Vector extends PinType
  case object Rotation extends PinType
  case object Truth extends PinType
  case object Constraint extends PinType
  case object Pull extends PinType

  case class Pointer(of: PinType) extends PinType

}

sealed trait PinDirection
object PinDirection {

  case object Input extends PinDirection
  case object Output extends PinDirection

}
Edges are directed, hyper in the form of One Output -> N Inputs, labeled by PinType I guess. That's why it's Pull and not Execution because one Before can connect to many Afters
case class Level(
  blocks: Set[Block],
  wires: Graph[Pin, DiHyperEdge]
)
ScalaGraph lets me define labels but I haven't done so here
Adam Rosien
@arosien
but each block type restricts the possible edge types, right?
Soren
@srnb_gitlab
(Pin is just Block + PinDefinition, Block is just BlockDefinition + Position)
Yeah, each BlockDefinition has a Vector[PinDefinition]
Adam Rosien
@arosien
oh, it's dynamically typed (sort of)
Soren
@srnb_gitlab
I mean
Hmm
I don't really see how
The game doesn't let you connect pins of different types
image.png
And all pin-types are known at "compile-time"
Adam Rosien
@arosien
i have cloned your project. i meant that something like Dirt doesn't encode at the type level what kinds of Pin it can connect to
that's modeled as a value
Soren
@srnb_gitlab
No. I tried that in an earlier project and I entered Shapeless hell
:grimacing:
Adam Rosien
@arosien
hehe gotcha
Soren
@srnb_gitlab
So instead I have a validate of Level -> Chain String that'll accumulate errors like that
Adam Rosien
@arosien
right
Soren
@srnb_gitlab
And by Shapeless hell, I mean I was accumulating a graph at compile time and compilation took minutes
(Think something like this)
Soren
@srnb_gitlab

Hmm. I'm close when I do something like this:

case class FancadeF[A](
  exports: Vector[Export],
  imports: Vector[Import[A]],
)

case class Export(
  template: Exists[Template],
  pin: PinDefinition
)

case class Import[A](
  child: A,
  theirExport: PinDefinition,
  ourPin: PinDefinition
)

It doesn't address:

  • Distinguishing between multiple templates, i.e. if I need two different Get Position blocks that reference different objects. However realistically that should be handled in a single FancadeF, and I shouldn't have multiple exported templates
  • Selecting pins, i.e. when I only need to take the width from "screen size" or etc
Adam Rosien
@arosien
(i need to get dinner ready, will probably be back later. thanks for explaining things.)
Soren
@srnb_gitlab
:+1: Dinner is soon for me too
Mark de Jong
@Fristi

So we have now the instrumentation stuff in tagless, would make sense for tracing to annotate generic data containers such a lists or options with how big they are or extract identifiers from the received type. How could we write middleware which annotates on such types? Like all transformations are now F ~> G but would it be possible to summon a type class which annotates that data ? Just sketching out loud:

trait ConstrainedFunctionK[F[_], G[_], T[_]] {
  def apply[A](fa: F[A])(implicit T: T[A]): G[A]
}
trait TraceData[A] {
  def trace(value: A): RIO[OpenTracing, Unit]
}

object TraceData {
  implicit def option[A]: TraceData[Option[A]] = new TraceData[Option[A]] {
    def trace(value: Option[A]): RIO[OpenTracing, Unit] = OpenTracing.tag("hasValue", value.isDefined)
  }

  implicit def list[A]: TraceData[List[A]] = new TraceData[List[A]] {
    def trace(value: List[A]): RIO[OpenTracing, Unit] = OpenTracing.tag("size", value.size)
  }

  implicit val any: TraceData[Any] = new TraceData[Any] {
    def trace(value: Any): RIO[OpenTracing, Unit] = ZIO.unit
  }
}

Where T[_] would be TraceData

However the ConstrainedFunctionK is not a valid natural transformation anymore.. :/

This is kind of aspect weaving in tagless final
Not sure if it would work...
Mark de Jong
@Fristi
Oh wow just seeing this typelevel/cats-tagless#141
You already got a head of me
:joy:
Brian P. Holt
@bpholt

I have an abstract class that defines an abstract type, for which I want to require an instance of InvariantK, e.g.:

abstract class Foo {
  type Bar[F[_]]
  implicit val barInvariantK: InvariantK[Bar]

  def bar[F[_]]: Bar[F]

  def helloWorld[F[_], G[_]](fk: F ~> G, gk: G ~> F): Bar[G] = 
    bar[F].imapK(fk)(gk)
}

This seems to work, but the implementation is kind of… boilerplatey? (AFAICT the implementing class has to explicitly specify the instance of InvariantK, instead of letting the compiler resolve it.)

Anyone know of a better way to restrict the Bar type alias to types for which an InvariantK[Bar] exists?

Adam Rosien
@arosien
i've only seen the style that you wrote.
what is Bar really? it's existential to the user of Foo, so it's a bit weird to imapK over it
Adam Rosien
@arosien
alternative you could require helloWorld to be passed the InvariantK, since that is the only place it's used.
abstract class Foo {
  type Bar[F[_]]

  def bar[F[_]]: Bar[F]

  def helloWorld[F[_], G[_]](fk: F ~> G, gk: G ~> F)(implicit barInvariantK: InvariantK[Bar]): Bar[G] = 
    bar[F].imapK(fk)(gk)
}
(although that makes helloWorld identical to imapK)
Brian P. Holt
@bpholt
I think this works:
abstract class Foo[Bar[_[_]] : InvariantK] {
  def bar[F[_]]: Bar[F]

  def helloWorld[F[_], G[_]](fk: F ~> G, gk: G ~> F): Bar[G] =
    bar[F].imapK(fk)(gk)
}
This is a (possibly-misguided) attempt to create an IOLambda class, similar to IOApp but for AWS Lambdas
I introduced the imapK to try to find a way to support algebras that require ConcurrentEffect in their construction, while still supporting tracing using Natchez (which, since it uses Kleisli, can't go above Concurrent)
Brian P. Holt
@bpholt
so in reality, it's more like this
abstract class ResourceIOLambda[Resources[_[_]] : InvariantK, A, B] {
  def resources[F[_] : ConcurrentEffect : ContextShift : Logger : Timer](blocker: Blocker)
                                                                        (req: A, context: Context): Resource[F, Resources[F]]

  def handleRequestF[F[_] : Concurrent : ContextShift : Logger : Timer : Trace](resources: Resources[F])
                                                                               (req: A, context: Context): F[B]

  private def handleRequest(input: IO[InputStream], 
                            output: IO[OutputStream], 
                            context: Context): IO[Unit] = {
    // … calls resources (without tracing) and then handleRequestF (with tracing)
  }
  final override def handleRequest(input: InputStream, output: OutputStream, context: Context): Unit =
    handleRequest(Sync[IO].delay(input), Sync[IO].delay(output), context)
      .unsafeRunSync()
}

handleRequestF is parameterized with F[_] instead of a concrete IO so tracing can be injected via Kleisli[IO, Span[IO], *]

Meaning the Resources[F] from resources needs to be converted to Resources[Kleisli[F, Span[F], *]] to be passed into handleRequestF

Brian P. Holt
@bpholt
or, concretely, Resources[IO] is converted to Resources[Kleisli[IO, Span[IO], *]]
Ben Spencer
@dangerousben
is there a way to generate a FunctorK for an algebra like this?
import cats.tagless.autoFunctorK

@autoFunctorK
trait Foo[F[_]]

@autoFunctorK
trait Bar[F[_]] {
  def test(): F[Foo[F]]
}
oh... I thought it was Bar it was failing to derive and I just realised the error is about Foo...
Ben Spencer
@dangerousben
could not find implicit value of type cats.tagless.FunctorK[[F[_]]F[ammonite.$sess.cmd1.Foo[F]]]
not really sure how to read that type
Georgi Krastev
@joroKr21
@dangerousben I think there is no way because given F ~> G and knowing nothing more about F or G we can only convert F[Foo[F]] to G[Foo[F]] but we can't peek inside F to convert the Foo. The type in the error message is how the compiler prints a type lambda F[_] => F[Foo[F]]. I guess it's always educational to try and write an instance FunctorK[Bar] by hand. If you can't (trivially) do it then it can't be derived automatically either. But it's a good way to convince yourself.
Georgi Krastev
@joroKr21
For example if we knew that F (or G or both) forms a functor we would be able to do it. But then we would need a constrained FunctorK only for algebras parameterized by functors.
Ben Spencer
@dangerousben
@joroKr21 ah, makes sense
Ben Spencer
@dangerousben
I guess the best I can do it define my own version of mapK specific to this algebra
Georgi Krastev
@joroKr21
Yes, that would work mapK with implicit functor requirement :thumbsup: