New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unboxed Forall #1417

merged 2 commits into from Sep 4, 2017


None yet
2 participants

TomasMikula commented Jun 28, 2017

Define Forall[F[_]] as an abstract type, privately implemented as

type Forall[F[_]] = F[Any]

A type alias is provided

type ∀[F[_]] = Forall[F]

Creating instances

Since Forall[F] is represented as F[Any], care needs to be taken so that only truly parametric instances can be created. Two ways to create instances are provided:

  1. From a "prototype", which is a Scalaz7-style universally quantified value:

    def from[F[_]](p: Prototype[F]): Forall[F]
    trait Prototype[F[_]] {
      def apply[A]: F[A]

    Prospectively, there could be convenient syntax for creating Prototypes via non/kind-projector#54.

    Note that creation via a prototype requires an allocation of a short-lived object (the prototype), but the resulting Forall[F] value is unboxed. (Perhaps that one allocation could be eliminated by the optimizer?)

  2. Via the same trick (due to @alexknvl) as in #1416:

    val l1: Forall[List] = Forall.of[List](Nil)
    // or
    val l2: Forall[List] =[Forall[List]].from(Nil)

    The seemingly longer mk[...].from(...) syntax becomes more succinct in some cases:

    def listSemigroup[A]: Semigroup[List[A]] = ???
    type Plus[F[_]] = Forall[λ[A => Semigroup[F[A]]]]
    val listPlus: Plus[List] = Forall.of[λ[A => Semigroup[F[A]]]](listSemigroup)
    // vs
    val listPlus: Plus[List] =[Plus[List]].from(listSemigroup)

Using instances

From user's perspective Forall[F] is completely abstract, but values are enriched with apply[A] method:

class ForallOps[F[_]](val a: Forall[F]) extends AnyVal {
  def apply[A]: F[A] = ???

One then uses this method to get an instance specialized for a specific type:

listPlus[Int].append(List(1, 2), List(3, 4)) // List(1, 2, 3, 4)

See also ForallUsage.scala on how Forall can be used to represent NaturalTransformation.

@TomasMikula TomasMikula added the scalaz8 label Jun 28, 2017


This comment has been minimized.


aloiscochard commented Jun 29, 2017

This is beautiful work, I ❤️ it.

What about adding the $ syntax directly in base? seems pretty useful to me.

Should we add this in default Prelude? I think yes.


This comment has been minimized.


TomasMikula commented Jun 30, 2017

In this PR, ~> is used just as an example. We can consider $ syntax when adding natural transformation. Though there might be confusion about preference, since a $ b $ c in Scala is (a $ b) $ c, whereas in Haskell it is a $ (b $ c). I used $ because Forall already has an apply method.

Yeah, I will add it to Prelude.


This comment has been minimized.


TomasMikula commented Jun 30, 2017

Added to Prelude. Maybe there's a better organization of the code?


This comment has been minimized.


aloiscochard commented Jul 10, 2017

Looks great!

@TomasMikula TomasMikula merged commit 7f3e5d3 into scalaz:series/8.0.x Sep 4, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed

@TomasMikula TomasMikula deleted the TomasMikula:unboxed-forall branch Sep 4, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment