Created
December 23, 2021 06:02
-
-
Save i10416/46e41cea6331e65fa66ef8df1c0abf1b to your computer and use it in GitHub Desktop.
generic vector representation using shapeless
This file contains 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
import $ivy.`com.chuusai::shapeless:2.3.7` | |
import shapeless._ | |
trait VecLike[T]{ | |
def dim:Int | |
def add(a:T,b:T):T | |
def sub(a:T,b:T):T | |
} | |
implicit def doubleVec2D:VecLike[(Double,Double)] = | |
new VecLike[(Double,Double)] { | |
def dim:Int = 2 | |
def add(a:(Double,Double),b:(Double,Double)):(Double,Double) = (a._1+b._1,a._2+b._2) | |
def sub(a:(Double,Double),b:(Double,Double)):(Double,Double) = (a._1 - b._1, a._2 - b._2) | |
} | |
implicit class VecLikeOps[T:VecLike](underlying:T) { | |
def dim:Int = implicitly[VecLike[T]].dim | |
def |+|(b:T) :T = implicitly[VecLike[T]].add(underlying,b) | |
def |-|(b:T):T = implicitly[VecLike[T]].sub(underlying,b) | |
} | |
implicit def numericVec2D[T:Numeric]:VecLike[(T,T)] = | |
new VecLike[(T,T)] { | |
def dim:Int = 2 | |
def add(a:(T,T),b:(T,T)):(T,T) = (Numeric[T].plus(a._1,b._1),Numeric[T].plus(a._2,b._2)) | |
def sub(a:(T,T),b:(T,T)):(T,T) = (Numeric[T].minus(a._1,b._1),Numeric[T].minus(a._2,b._2)) | |
} | |
trait GenericVecLike[L<: HList] extends VecLike[L] {type Elm} | |
object GenericVecLike { | |
type Aux[L<:HList,A] = GenericVecLike[L]{ type Elm = A} | |
implicit def empty[A]:Aux[HNil,A] = new GenericVecLike[HNil] { | |
type Elm = A | |
def dim = 0 | |
def add(a:HNil,b:HNil):HNil = HNil | |
def sub(a:HNil,b:HNil):HNil = HNil | |
} | |
implicit def cons[T<:HList,A:Numeric](implicit tail:Aux[T,A]):Aux[A::T,A] = new GenericVecLike[A::T] { | |
type Elm = A | |
def dim: Int = tail.dim + 1 | |
def add(a: A :: T, b: A :: T): A :: T = Numeric[A].plus(a.head,b.head) :: tail.add(a.tail,b.tail) | |
def sub(a: A :: T, b: A :: T): A :: T = Numeric[A].minus(a.head,b.head) :: tail.sub(a.tail,b.tail) | |
} | |
} | |
implicit def genericVec[T,Repr <: HList](implicit gen:Generic.Aux[T,Repr],instance:GenericVecLike[Repr]):VecLike[T] = new VecLike[T] { | |
def dim: Int = instance.dim | |
def add(a: T, b: T): T = gen.from(instance.add(gen.to(a),gen.to(b))) | |
def sub(a: T, b: T): T = gen.from(instance.sub(gen.to(a),gen.to(b))) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment