Skip to content

Generalize polymorphic functions to arbitrary polymorphic values #37

@TomasMikula

Description

@TomasMikula

Would it be feasible to extend this approach to arbitrary polymorphic values? Essentially, providing syntax for scalaz.Forall:

/** A universally quantified value */
trait Forall[P[_]] {
  def apply[A]: P[A]
}

The polymorphic function is then just a special case:

type NaturalTransformation[F[_], G[_]] = Forall[λ[A => (F[A] => G[A])]]

The syntax could be

val f = [λ[A => (List[A] => Option[A])]](_.headOption)

or in general

val f = [F](<expr>)

where

  • F[_] is a unary type constructor;
  • <expr> is an expression of type Function0[F[_]].

The resulting type of f is then Forall[F].

One benefit of this is that you don't need special named traits for polymorphic functions anymore (there is scalaz.~> and cats.FunctionK, which are basically the same, but incompatible—one needs conversions between them).

The main benefit, however, is that we would have syntax for other polymorphic values, like

[λ[A => Lens[F[A], G[A]]]]

Then given

trait Lens[S, A] {
  def get(s: S): A
  def set(s: S, a: A): S
}
object Lens {
  def apply[S, A](get: S => A, set: (S, A) => S): Lens[S, A] = ???
}

we could define a polymorphic lens

val fstLens = [λ[A => Lens[(A, Int), Id[A]]]](Lens(_._1, (ai, a) => (a, ai._2)))

where fstLens has type Forall[λ[A => Lens[(A, Int), Id[A]]]]. This would then be used like this

val x = ("Hello", 5)
fstLens[String].get(x) // "Hello"
fstLens[String].set(x, "Bye") // ("Bye", 5)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions