模糊隐含值是我们想要在编译时存在错误的唯一方法

Xia*_*ong 5 scala type-safety shapeless

trait Foo

trait Bar extends Foo

def doStuff[T <: Foo](x: T)(implicit ev: T =!:= Foo) = x

doStuff(new Foo{}) //ambiguous implicit value
doStuff(new Bar)// successful
Run Code Online (Sandbox Code Playgroud)

隐式解决方案正在编译时发生,所以在这里我认为可能有两个隐式值具有完全相同的类型来触发模糊的东西.

现在,我将在团队中引入无形的,我的同事们认为这种含糊不清的暗示并不理想,我对此没有强烈的争论.这是实现它的唯一方法,以便在scala中使类型安全.如果是,我该怎么做才能自定义错误消息?

编辑:

在无形状中,我想使2 NAT的总和不等于7,我可以像这样编码使编译失败.

def typeSafeSum[T <: Nat, W <: Nat, R <: Nat](x: T, y: W)
         (implicit sum: Sum.Aux[T, W, R], error: R =:!= _7) = x

typeSafeSum(_3, _4)
Run Code Online (Sandbox Code Playgroud)

但错误信息是含糊不清的隐含值,如何自定义错误信息?

Mil*_*bin 7

一个简单的类型类比这个(以及大多数其他)实例中的类型不等式测试更好.

据推测,想要排除的原因FooBar(和它的兄弟姐妹)有一些Foo缺乏的属性.如果是这种情况,那么你应该创建一个类型类来捕获这些属性并使其成为type参数的要求doStuff.您可以使用Scala的@implicitNotFound注释,以便在不满足该要求时使编译器错误消息更易于理解.

@annotation.implicitNotFound(msg = "No Props instance for ${T}")
trait Props[T] {
  def wibble(t: T): Double
}

trait Foo
// Note no Props instance for Foo ...

trait Bar extends Foo
object Bar {
  // Props instance for Bar
  implicit def barProps: Props[Bar] = new Props[Bar] {
    def wibble(t: Bar): Double = 23.0
  }
}

def doStuff[T <: Foo](t: T)(implicit props: Props[T]) = props.wibble(t)

scala> doStuff(new Foo {})
<console>:11: error: No Props instance for Foo
              doStuff(new Foo {})
                     ^

scala> doStuff(new Bar {})
res1: Double = 23.0
Run Code Online (Sandbox Code Playgroud)

如果没有任何这样的特性,这区分FooBar,那么你应该质疑你的假设,你需要排除FoodoStuff摆在首位.

如果您在项目中使用无形,我会很高兴,但您应该使用=!:=(和Scala自己的=:=)作为最后的手段,如果有的话.