Skip to content

Instantly share code, notes, and snippets.

@jestan
Forked from retronym/type-bounds.scala
Created April 19, 2012 16:00
Show Gist options
  • Select an option

  • Save jestan/2421981 to your computer and use it in GitHub Desktop.

Select an option

Save jestan/2421981 to your computer and use it in GitHub Desktop.

Revisions

  1. @retronym retronym revised this gist Jun 6, 2010. 1 changed file with 25 additions and 1 deletion.
    26 changes: 25 additions & 1 deletion type-bounds.scala
    Original file line number Diff line number Diff line change
    @@ -80,4 +80,28 @@ def combo[AA >: B <: A](implicit
    implicit def MofA: M[A] = new M[A] {}
    contextBound(new A)
    }
    }
    }


    implicit def int2str(i: Int): String = i.toString
    def f1[T <% String](t: T) = 0
    f1(1)

    // This could also be expressed with a Context Bound,
    // with the help of a type alias representing functions
    // from type `F` to type `T`.

    trait To[T] { type From[F] = F => T }
    def f2[T : To[String]#From](t: T) = 0
    f2(1)

    // A context bound must be used with a type constructor of kind `* => *`.
    // However the type constructor `Function1` is of kind `(*, *) => *`.
    // The use of the type alias partially applies second type parameter
    // with the type `String`, yielding a type constructor of the correct kind
    // for use as a context bound.

    // There is a proposal to allow you to directly express partially applied types
    // in Scala, without the use of the type alias inside a trait. You could then write:
    //
    // def f3[T : [X](X => String)](t: T) = 0
  2. @retronym retronym revised this gist Apr 30, 2010. 1 changed file with 13 additions and 1 deletion.
    14 changes: 13 additions & 1 deletion type-bounds.scala
    Original file line number Diff line number Diff line change
    @@ -35,14 +35,26 @@ def viewBound[AA <% A](x: AA): A = x
    def viewBound$[AA](x: AA)(implicit ev1$ : AA => A) = ev1$(x)


    //
    //
    // Context Bound
    //
    def contextBound[X: M](x: X) = x;

    //compiles to:
    def contextBound$[X](x: X)(implicit ev1$ : M[X]) = x

    // In combination:

    def combo[AA <: A >: B <% String <% Int : M : Ordering] = 0

    // compiles to:
    def combo[AA >: B <: A](implicit
    evidence$1: (AA) => String,
    evidence$2: (AA) => Int,
    evidence$3: M[AA],
    evidence$4: Ordering[AA]
    ): Int = 0

    //
    // Usage
    //
  3. @retronym retronym revised this gist Dec 17, 2009. 1 changed file with 41 additions and 8 deletions.
    49 changes: 41 additions & 8 deletions type-bounds.scala
    Original file line number Diff line number Diff line change
    @@ -1,23 +1,29 @@
    class A
    class A2 extends A
    class B

    trait M[X]

    //
    // Upper Type Bound
    //
    def upperTypeBound[AA <: A](x: AA): A = x

    // equivalently, require a implicit parameter of <:<[AA, A].
    // equivalently, require a implicit parameter of <:<[AA, A].
    // This technique must be used if A is an abstract type from the
    // enclosing scope.
    def upperTypeBound2[AA](x: AA)(implicit ev: AA <:< A): A = x // compiles to ev(x)
    def upperTypeBound2[AA](x: AA)(implicit ev: AA <:< A): A = x // compiles to ev(x)


    //
    // Lower Type Bound
    //
    def lowerTypeBound[AA :> A](x: AA, pred: (AA => Boolean)): Boolean = pred(x)
    def lowerTypeBound[AA >: A](x: AA, pred: (AA => Boolean)): Boolean = pred(x)

    // equivalently, require a implicit parameter of <:<[A, AA].
    // equivalently, require a implicit parameter of <:<[A, AA].
    // This technique must be used if A is an abstract type from the
    // enclosing scope.
    def lowerTypeBound2[AA :> A](x: AA, pred: (AA => Boolean))(implicit ev: A <:< AA): Boolean = pred(x)
    def lowerTypeBound2[AA >: A](x: AA, pred: (AA => Boolean))(implicit ev: A <:< AA): Boolean = pred(x)


    //
    @@ -26,13 +32,40 @@ def lowerTypeBound2[AA :> A](x: AA, pred: (AA => Boolean))(implicit ev: A <:< AA
    def viewBound[AA <% A](x: AA): A = x

    //compiles to:
    def viewBound$[AA](x: AA)(implicit ev1$: AA => A) = ev1$(x)
    def viewBound$[AA](x: AA)(implicit ev1$ : AA => A) = ev1$(x)


    //
    // Context Bound
    //
    def contextBound[X: B](x: X)
    def contextBound[X: M](x: X) = x;

    //compiles to:
    def contextBound$[X](x: X)(implicit ev1$: B[X])
    def contextBound$[X](x: X)(implicit ev1$ : M[X]) = x

    //
    // Usage
    //
    {
    {

    upperTypeBound(new A)
    upperTypeBound(new A2)
    }

    {
    val predA = (a: A) => true
    val predAny = (a: Any) => true
    lowerTypeBound(new A, predA)
    lowerTypeBound(new {}, predAny)
    }

    {
    implicit def String2A(s: String): A = new A
    viewBound("")
    }
    {
    implicit def MofA: M[A] = new M[A] {}
    contextBound(new A)
    }
    }
  4. @retronym retronym revised this gist Dec 17, 2009. 1 changed file with 12 additions and 1 deletion.
    13 changes: 12 additions & 1 deletion type-bounds.scala
    Original file line number Diff line number Diff line change
    @@ -4,11 +4,22 @@
    def upperTypeBound[AA <: A](x: AA): A = x

    // equivalently, require a implicit parameter of <:<[AA, A].
    // This method must be used if A is an abstract type from the
    // This technique must be used if A is an abstract type from the
    // enclosing scope.
    def upperTypeBound2[AA](x: AA)(implicit ev: AA <:< A): A = x // compiles to ev(x)


    //
    // Lower Type Bound
    //
    def lowerTypeBound[AA :> A](x: AA, pred: (AA => Boolean)): Boolean = pred(x)

    // equivalently, require a implicit parameter of <:<[A, AA].
    // This technique must be used if A is an abstract type from the
    // enclosing scope.
    def lowerTypeBound2[AA :> A](x: AA, pred: (AA => Boolean))(implicit ev: A <:< AA): Boolean = pred(x)


    //
    // View Bound
    //
  5. @retronym retronym revised this gist Dec 17, 2009. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions type-bounds.scala
    Original file line number Diff line number Diff line change
    @@ -1,21 +1,21 @@
    //
    // Upper Type Bound
    //
    def upperTypeBound[AA <: A](x: AA)
    def upperTypeBound[AA <: A](x: AA): A = x

    // equivalently, require a implict parameter of <:<[AA, A].
    // equivalently, require a implicit parameter of <:<[AA, A].
    // This method must be used if A is an abstract type from the
    // enclosing scope.
    def upperTypeBound2[AA](x: AA)(implicit ev: AA <:< A)
    def upperTypeBound2[AA](x: AA)(implicit ev: AA <:< A): A = x // compiles to ev(x)


    //
    // View Bound
    //
    def viewBound[AA <% A](x: AA)
    def viewBound[AA <% A](x: AA): A = x

    //compiles to:
    def viewBound$[AA](x: AA)(implicit ev1$: AA => A)
    def viewBound$[AA](x: AA)(implicit ev1$: AA => A) = ev1$(x)


    //
  6. @retronym retronym revised this gist Dec 16, 2009. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion type-bounds.scala
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,9 @@
    //
    def upperTypeBound[AA <: A](x: AA)

    //alternatively
    // equivalently, require a implict parameter of <:<[AA, A].
    // This method must be used if A is an abstract type from the
    // enclosing scope.
    def upperTypeBound2[AA](x: AA)(implicit ev: AA <:< A)


  7. @retronym retronym created this gist Dec 16, 2009.
    25 changes: 25 additions & 0 deletions type-bounds.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    //
    // Upper Type Bound
    //
    def upperTypeBound[AA <: A](x: AA)

    //alternatively
    def upperTypeBound2[AA](x: AA)(implicit ev: AA <:< A)


    //
    // View Bound
    //
    def viewBound[AA <% A](x: AA)

    //compiles to:
    def viewBound$[AA](x: AA)(implicit ev1$: AA => A)


    //
    // Context Bound
    //
    def contextBound[X: B](x: X)

    //compiles to:
    def contextBound$[X](x: X)(implicit ev1$: B[X])