Last active
December 28, 2015 01:29
-
-
Save zobar/7420886 to your computer and use it in GitHub Desktop.
Dimensional analysis in Scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/project | |
/target |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package abelian | |
trait Operation[-A <: Element, -B <: Element, +C <: Element] extends ((A, B) => C) | |
object Operation { | |
def apply[A <: Element, B <: Element, C <: Element](operation: (A, B) => C): Operation[A, B, C] = | |
new Operation[A, B, C] { def apply(a: A, b: B): C = operation(a, b) } | |
implicit def `*_identity`[A <: NonIdentity] = | |
Operation[A, Identity.type, A]((a, b) => a) | |
implicit def `*_inverse`[A <: Element, B <: Element](implicit operation: Operation[A, B, *[A, B]]) = | |
Operation[A, B#Inverse, *[A, B#Inverse]]((a, b) => new *(a, b)) | |
implicit def `*_myInverse`[A <: Element, B <: Element](implicit evidence: A =:= B#Inverse) = | |
Operation[A, B, Identity.type]((a, b) => Identity) | |
implicit def commutative[A <: Element, B <: Element, C <: Element](implicit operation: Operation[B, A, C]): Operation[A, B, C] = | |
Operation((a, b) => operation.apply(b, a)) | |
} | |
trait Element { | |
type Inverse <: Element | |
def *[A <: Element, B <: Element](factor: A)(implicit operation: Operation[this.type, A, B]): B = | |
operation(this, factor) | |
val inverse: Inverse | |
} | |
object Identity extends Element { | |
type Inverse = Identity.type | |
val inverse = this | |
override def toString = "1" | |
} | |
trait NonIdentity extends Element | |
trait Basic extends NonIdentity { | |
basic => | |
class Inverse private[Basic] extends NonIdentity { | |
type Inverse = basic.type | |
val inverse: Inverse = basic | |
override def toString = s"$basic-1" | |
} | |
protected[this] def *[A <: Element] = | |
Operation[this.type, A, *[this.type, A]]((a, b) => new *(this, b)) | |
val inverse = new Inverse | |
} | |
class *[A <: Element, B <: Element](val a: A, val b: B) extends NonIdentity { | |
type Inverse = *[A#Inverse, B#Inverse] | |
lazy val inverse = ??? // a.Inverse * b.Inverse | |
override def toString = s"$a.$b" | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
scalacOptions ++= Seq("-feature") | |
scalaVersion := "2.10.3" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dimension | |
import abelian.{Basic => Dimension} | |
object Length extends Dimension { | |
override def toString = "L" | |
implicit def `*_mass` = *[Mass.type] | |
implicit def `*_time` = *[Time.type] | |
} | |
object Mass extends Dimension { | |
override def toString = "M" | |
implicit def `*_time` = *[Time.type] | |
} | |
object Time extends Dimension { | |
override def toString = "T" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment