简体   繁体   English

强制对特征“ F”的方法进行某种类型“ T”的所有输入以前都是由“ F”本身产生的

[英]Enforce that all inputs of some type `T` to methods of a trait `F` have been previously produced by `F` itself

Suppose that I have some trait Foo , for example: 假设我有一些特征Foo ,例如:

trait Foo {
  def bar: List[Int]
  def baz(i: Int): Unit
}

I want to enforce at compile time that all inputs passed to baz have been previously produced by bar . 我想在编译时强制所有传递给baz输入都是bar先前产生的。 For example, if this is an implementation of Foo : 例如,如果这是Foo的实现:

object A extends Foo {
  def bar = List(2, 3, 5, 7)
  def baz(i: Int): Unit = {
    if (bar contains i) println("ok")
    else println("not good")
  }
}

then I want to enforce that only single-digit primes can be passed to baz . 然后我要强制只将个位数的素数传递给baz This obviously doesn't work if the input type of baz is known to be Int , because it allows me to instantiate all kinds of integers that are not prime and not between 0 and 9 : 如果已知baz的输入类型为Int ,则这显然不起作用,因为它允许我实例化所有不是素数且不在09之间的整数:

val okValues: List[Int] = A.bar
A.baz(okValues(1)) // ok
A.baz(3)           // ok (but dangerous! `3` appeared out of nowhere!)
A.baz(42)          // not good

How can I enforce that only the values previously produced by bar can be passed to baz ? 我该如何强制只将先前由bar生成的值传递给baz


What doesn't work 什么不起作用

Converting Int to a type member of Foo doesn't help, because it's instantiated to the concrete type Int in the implementation A of Foo : Int转换为Foo的类型成员没有帮助,因为它在Foo的实现A中实例化为具体的Int类型:

trait Foo {
  type T
  def bar: List[T]
  def baz(t: T): Unit
}

object A extends Foo {
  type T = Int 
  def bar = List(2, 3, 4, 5)
  def baz(i: Int): Unit = {
    if (bar contains i) println("ok")
    else println("not good")
  } 
}

A.baz(42) // not good

Here is one solution that relies on replacing a concrete type Int by an abstract type member T , and then simply not exposing the concrete implementation of T by Int : 这是一个解决方案,它依赖于用抽象类型成员T替换具体类型Int ,然后简单地不通过Int公开T的具体实现:

  • replace the concrete type Int by an abstract type member T 用抽象类型成员T替换具体的Int类型
  • move methods bar and baz and the type T into an inner trait YFoo 将方法barbaz以及类型T到内部特征YFoo
  • inside Foo , provide a method that produces YFoo , but does not expose what T is. Foo内部,提供一种生成YFoo的方法,但不公开T是什么。

In code: 在代码中:

trait Foo {
  trait YFoo {
    type T
    def bar: List[T]
    def baz(i: T): Unit
  }
  def yFoo: YFoo
}

object B extends Foo {
  def yFoo: YFoo = new YFoo {
    type T = Int
    def bar: List[Int] = List(2, 3, 5, 7)
    def baz(i: Int): Unit = {
      if (bar contains i) println("ok")
      else println("not good")
    }
  }
}

val a = B.yFoo
val okValues: List[a.T] = a.bar
a.baz(okValues(1)) // ok
// a.baz(3)           // dangerous stuff doesn't compile!
// found   : Int(3)
// required: a.T

// a.baz(42)          // invalid stuff also doesn't compile
// found   : Int(42)
// required: a.T

Now all the dangerous / invalid stuff doesn't even compile. 现在,所有危险/无效的东西甚至都无法编译。 The only values that you can pass to baz are those from the "list of certified values" produced by bar . 可以传递给baz的唯一值是bar产生的“认证值列表”中的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使F界多态性可用于具有类型参数的基本特征? - Getting F-bounded polymorphism to work on a base trait with type parameters? F[_] 和 F[T] 在 Scala 中用于类型构造函数时的区别 - Difference between F[_] and F[T] In Scala when used in type constructors F-bounded类型和方法,在参数和返回站点具有类型参数 - F-bounded types and methods with type parameters at argument and return sites scala:使用F绑定参数引用特性 - scala: Referencing Trait with F-Bound Parameters 为什么方法参数 F 可以与类型构造函数 F 同名? - Why can method parameter F have the same name as type constructor F? 如何检查宏中的F [T] &lt;:G [T] forAll {type T} - How to check if F[T] <: G[T] forAll { type T } in a macro Scala是否具有F#的“类型”? - Does Scala have an equivalent of F#'s “type of”? 不能使用类型投影到递归(f边界)类型 - Can't use a type projection to a recursive (f-bounded) type 混入时,scala编译器可以强制实施抽象特征方法吗? - Can scala compiler enforce to implement abstract trait methods when mixin in? 将Shapelessless Hlist类型F [T1] ::…:: F [Tn] :: HNil映射到类型T1 ::…:: Tn :: HNil(类型级别排序) - Map Shapeless hlist type F[T1] :: … :: F[Tn] :: HNil to the type T1 :: … :: Tn :: HNil (type level sequencing)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM