Skip to content

Instantly share code, notes, and snippets.

@mosesn
Last active August 29, 2015 13:56
Show Gist options
  • Save mosesn/9014381 to your computer and use it in GitHub Desktop.
Save mosesn/9014381 to your computer and use it in GitHub Desktop.
import scala.language.implicitConversions
class Mult[A, B] {
def commute: Mult[B, A] = new Mult[B, A]
def associate[C, D](implicit ev: B =:= Mult[C, D]): Mult[Mult[A, C], D] = new Mult[Mult[A, C], D]
}
object Simplify {
implicit def commute[A, B, M <% Mult[A, B]](m: M): Mult[B, A] = m.commute
implicit def associate[A, B, C, M <% Mult[A, Mult[B, C]]](m: M): Mult[Mult[A, B], C] = m.associate
}
object TryIt {
import Simplify._
class Cat
class Dog
class Mouse
val x: Mult[Cat, Dog] = new Mult[Dog, Cat]
val y: Mult[Mult[Cat, Dog], Mouse] = new Mult[Cat, Mult[Dog, Mouse]]
val z: Mult[Mouse, Mult[Cat, Dog]] = new Mult[Cat, Mult[Dog, Mouse]] // this requires chaining, but chaining diverges
/*
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=utf8
./multiplication.scala:20: error: diverging implicit expansion for type Mult[TryIt.Dog,TryIt.Cat] => Mult[TryIt.Dog,TryIt.Cat]
starting with method commute in object Simplify
val x: Mult[Cat, Dog] = new Mult[Dog, Cat]
^
./multiplication.scala:21: error: type mismatch;
found : Mult[TryIt.Cat,Mult[TryIt.Dog,TryIt.Mouse]]
required: Mult[Mult[TryIt.Cat,TryIt.Dog],TryIt.Mouse]
Note that implicit conversions are not applicable because they are ambiguous:
both method associate in object Simplify of type [A, B, C, M](m: M)(implicit evidence$2: M => Mult[A,Mult[B,C]])Mult[Mult[A,B],C]
and method commute in object Simplify of type [A, B, M](m: M)(implicit evidence$1: M => Mult[A,B])Mult[B,A]
are possible conversion functions from Mult[TryIt.Cat,Mult[TryIt.Dog,TryIt.Mouse]] to Mult[Mult[TryIt.Cat,TryIt.Dog],TryIt.Mouse]
val y: Mult[Mult[Cat, Dog], Mouse] = new Mult[Cat, Mult[Dog, Mouse]]
^
./multiplication.scala:22: error: diverging implicit expansion for type Mult[TryIt.Cat,Mult[TryIt.Dog,TryIt.Mouse]] => Mult[Mult[TryIt.Cat,TryIt.Dog],TryIt.Mouse]
starting with method commute in object Simplify
val z: Mult[Mouse, Mult[Cat, Dog]] = new Mult[Cat, Mult[Dog, Mouse]] // this requires chaining, but chaining diverges
^
three errors found
*/
}
import scala.language.implicitConversions
class Mult[A, B] {
def commute: Mult[B, A] = new Mult[B, A]
def associate[C, D](implicit ev: B =:= Mult[C, D]): Mult[Mult[A, C], D] = new Mult[Mult[A, C], D]
}
object Simplify {
implicit def commute[A, B](m: Mult[A, B]): Mult[B, A] = m.commute
implicit def associate[A, B, C](m: Mult[A, Mult[B, C]]): Mult[Mult[A, B], C] = m.associate
}
object TryIt {
import Simplify._
class Cat
class Dog
class Mouse
val x: Mult[Cat, Dog] = new Mult[Dog, Cat]
val y: Mult[Mult[Cat, Dog], Mouse] = new Mult[Cat, Mult[Dog, Mouse]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment