2016-09-06 4 views
0

scalas 유형 체계로 놀고 있고 다시 나는 나 자신이 그것을 싸우는 찾아 낸다. 몇 가지 간단한 그래픽 응용 프로그램을위한 Vector 라이브러리를 만들었습니다.scala higher 종류와 scalatic 동등한

이제 scalacheck 및 scalatest를 사용하여 Vector 속성을 테스트 할 수 있기를 원합니다. 지금 당면한 문제는 복소수 또는 부동 소수점을 사용할 때 벡터 평등을 검사하는 것이 내가 생각한 것처럼 간단하지 않다는 것입니다. 이제 테스트 프레임 워크에서 가장 관용적 인 방법은 내 벡터 클래스에 new Equality을 만드는 것이라고 생각했습니다. 그러나 이제 한 걸음 뒤로 물러나 내 벡터 defenitions 또한 여기에 적용 취소 표시되지

abstract class Vec[T, V[T] <: Vec[T, V]](val elems: T*)(implicit num: VecIntegral[T], factory: VecFactory[V]) 
class Vec2[T](x: T, y: T)(implicit num: VecIntegral[T]) extends Vec[T, Vec2](x,y) 
Vec3[T](x: T, y: T, z: T)(implicit num: VecIntegral[T]) extends Vec[T, Vec3](x,y, z) 

를 살펴보고 패턴 매칭 등을 위해 허용 VEC 객체에 대해 정의 된 적용 할 수 있습니다.

는 이제 쓰기 시험에 대한 내 첫 번째 시도는 다시 여기에 내가 공연을 해달라고하지만 난 Vec2[T]Vec3[T] 클래스를 구현 암시 공장을 가지고이

abstract class VecSuite[T: Arbitrary, V[T] <: Vec[T, V]](implicit genVec: Arbitrary[V[T]], num: VecIntegral[T]) 
    extends PropSpec with PropertyChecks { 
    import num._ 

    property("associative add") { 
    forAll { (a: V[T], b: V[T]) => 
     assert((a + b).===(b + a)) 
    } 
    } 

    property("scalar distributed") { 
    forAll { (a: V[T], b: V[T], s: T) => 
     assert((a + b) * s === a * s + b * s) 
    } 
    } 
... 
} 
class Vec2IntSuite extends VecSuite[Int, Vec2] 
class Vec2FloatSuite extends VecSuite[Float, Vec2] 
class Vec2DoubleSuite extends VecSuite[Double, Vec2] 
class Vec2LongSuite extends VecSuite[Long, Vec2] 

같은 것을 보인다.

정말 잘 작동합니다. FloatDouble에 대해 반올림 오류가 발생하고 평등 검사가 불어 나오는 것을 제외하고는 일반적인 테스트를 작성하고 지원되는 모든 다른 Vector 구현에 적용 할 수 있습니다. 그래서

는 지금은 Equality 클래스가 일반 Vec2 사이에 난 단지 DoubleFloat 시도 두 암시 적 값을 필요로하므로 Vec2 만들려고 노력과 주변의 재생을 시작 :

implicit val doubleEq = new Equality[ V[Double] forSome{ type V[Double] <: Vec[Double, V] }] { 
    override def areEqual(a: V[Double] forSome {type V[Double] <: Vec[Double, V]}, b: Any): Boolean = (a,b) match { 
    case (lhs: Vec[Double, _], rhs: Vec[Double, _]) => lhs.elems.zip(rhs.elems).forall {case (e1, e2) => e1 === e2 +- 0.01d } 
    case _ => false 
    } 
} 

을하지만이 앉아하지 않습니다 컴파일러를 잘 사용하면 java.lang.StackOverflowException으로 불어납니다. 그만큼이 유형 Double입니다으로 Vec2 또는 Vec3 경우

는 암시 적으로 내을 testcases에서 사용될 수 있도록 Equality의 유형을 작성하는 방법은 없나요이 선명하게 촬상?

답변

0

좋아, 나는 이것을 실제로 풀었다!

class VecDoubleEquality[V[Double] <: Vec[Double, V]] extends Equality[V[Double]] { 
    override def areEqual(a: V[Double], b: Any): Boolean = (a,b) match { 
    case (lhs: Vec[Double, V], rhs: Vec[Double, V]) => lhs.elems.zip(rhs.elems).forall {case (e1, e2) => e1 === e2 +- 0.1d } 
    case _ => false 
    } 
} 
implicit def doubleEq[V[Double] <: Vec[Double, V]] = new VecDoubleEquality[V] 

이 올바르게 forSome 존재 비트 귀찮게하지 않고 나에게 재귀 유형 올바른 유형의 서명을 제공 할 것입니다.