2017-05-13 1 views
3

스칼라에서 타입 레벨 프로그래밍에 대해 더 자세히 배우고 싶었고 몇 가지 작은 연습을 시작했습니다. 유형 수준에서 Peano 숫자 구현을 시작했습니다. 아래 코드가 있습니다!스칼라에서 타입 레벨 프로그래밍

sealed trait PeanoNumType { // Type at the end indicates to the reader that we are dealing with types 
    type plus[That <: PeanoNumType] <: PeanoNumType 
} 

sealed trait ZeroType extends PeanoNumType { 
    type plus[That <: PeanoNumType] = That 
} 

sealed trait NextType[This <: PeanoNumType] extends PeanoNumType { 
    type plus[That <: PeanoNumType] = NextType[This#plus[That]] 
} 

이제 위의 구현을 통해 나에게 맞는 것이 무엇이겠습니까? 어떻게 활용할 수 있습니까?

답변

6

이러한 유형을 직접 만들어야하는 경우 많은 것을 제공하지 않습니다. 하지만, 컴파일러가 당신을 위해 작업을 수행하자마자 훨씬 더 유용 할 것입니다.

나는이 보여 전에, 짧은 무언가로 페 아노의 aritmetic을 표현하는 방법으로 변경할 수 있습니다 :

sealed abstract class List[+H, N <: Num](val size: N) { 
    def ::[T >: H](value: T): List[T, Succ[N]] = Cons(value, this) 
} 
case object Nil extends List[Nothing, Zero.type](Zero) 
case class Cons[+H, N <: Num](head: H, tail: List[H, N]) extends List[H, Succ[N]](Succ(tail.size)) 
type ::[+H, N <: Num] = Cons[H, N] 

당신 경우 :

sealed trait Num 
case object Zero extends Num 
case class Succ[N <: Num](num: N) extends Num 

당신은 다음 컴파일 타임에 알려진 크기의 목록을 만들 수를 Sych 목록으로 생성 된 sth의 유형을 확인하십시오. 형식으로 인코딩 된 크기를 갖습니다.

val list = 1 :: 2 :: 3 :: 4 :: Nil // List[Int, Succ[Succ[Succ[Succ[Zero.type]]]]] = Cons(1,Cons(2,Cons(3,Cons(4,Nil)))) 

다음으로 시도 할 수있는 것은 암시를 사용하여 무언가를 검사하는 것입니다 (예 :

def operationForEvenSizeList[T, N <: Num](list: List[T, N])(implicit ev: EvenNum[N]) = { 
    // do something with list of even length 
} 

operationForEvenSizeList(1 :: 2 :: Nil) // ok 
operationForEvenSizeList(1 :: 2 :: 3 :: Nil) // compiler error 

을 지금까지 스칼라 때 나타나는에서 I 타입 레벨의 프로그래밍의 진정한 힘을 말할 수 : 당신이 암시 적 증거를 제공 할 수있을 때 일부 작업 만 수행 될 수 있음을 시행 할 수있는와

trait EvenNum[N <: Num] 
implicit val zeroIsEven = new EvenNum[Zero.type] {} 
implicit def evenNPlusTwo[N <: Num](implicit evenN: EvenNum[N]) = new EvenNum[Succ[Succ[N]]] {} 

암시 적 증거, 유형 - 클래스 유도 및 일부 구조적 보일러 플레이트 제거에 사용할 수있는 새로운 유형을 생성하기위한 암시를 사용하기 시작합니다.

일반 프로그래밍으로 많은 도움을주는 라이브러리는 쉐이프가 아닙니다. 일단 당신이 implicits를 가진 몇몇 종류 종류 유도를 가진 운동 또는 2를 할 일단 당신이를 사용하는 재미있는 물건 일 것이라고 믿습니다.

코드로 돌아가서 : 클래스의 인스턴스를 생성하고 제공 할 수있는 몇 가지 암시를 제공 할 수 있습니다. 또한 새 클래스를 만드는 것 외에도이 코드는 다른 작업을 수행합니다. 그러한 클래스에 추가 할 요소 목록을 결합하거나 PeanoNumType에서 Int로 변환하거나 컴파일 타임에 작동하는 일부 술어를 추가하는 등 Sky가 한계입니다.

관련 문제