2016-12-09 33 views
2

具体值给出:构建列表与在编译时

case class Foo(x: BigDecimal)

我想,在编译时,构建一个List[Foo]每个Foo必须有5一个BigDecimal值。

所以,我希望下面的代码进行编译:

type Foo5Only = ??? 

val foos5: List[Foo5Only] = List(Foo(5), Foo(5)) 

但是,我期望下无法编译:

val bad: List[Foo5Only] = List(Foo(42))

我猜测,一个shapeless单身类型可能很有用,但我实际上并没有理解它。

注 - 我对这个问题没有兴趣,导致使用EitherOption

+0

需要BigDecimal吗? (否则,你可能可以使用'Nat'和参数化'Foo') –

+0

@MichaelZajac - 是的,'Nat'会工作,谢谢。对于我自己的学习,Singleton类型是否适用于此 - 作为“Nat”的替代方案? –

回答

1

除了使用无形的'Nat类型,你也可以使用单身类型。不幸的是Scala的内置列表类型具有协方差它得到的类型安全的方式,而是用一个简单的手工制作的列表类型似乎工作:

import shapeless.syntax.singleton._ 

sealed trait Lst[T] 
case class Nil[T]() extends Lst[T] 
case class Cons[T](head : T, tail : Lst[T]) extends Lst[T] 

def list[T](t : T) : Lst[T] = { 
    Cons(t, Nil()) 
} 

// OK 
val foos5 = Cons(5.narrow, list(5.narrow)) 

// Compile-time type mismatch error. 
val foos6 = Cons(42.narrow, list(5.narrow)) 

您或许能够与一些宏的Elid的narrow小号 - 可能,但这超出了我的能力。