scala - Scala 3 TypeTest over Union 似乎无法正常工作
问题描述
只是玩弄一些 Scala 3 功能,我正在定义一个BooleanAlgebra[A]
其中有T <: A
和B <: A
. 这些类型用于检查类型 A 是否已规范化,我们不再需要检查它的边界。
Normailize 给了我们T | F
TypeTests 当然是必需的,因为类型T
和F
在运行时被擦除。
该示例可以正常工作,但是它抱怨即使在我匹配的任何时候匹配项都不是详尽无遗的,即使来自和 fromT | F
的 TypeTag 也是如此。注意我添加了语句,以便您可以看到它的工作。T | F => T
T | F => F
println
A => T | F
从,添加 TypeTagsA => T
也A => F
不起作用。N 是必需的,因为 Scala 3 似乎不喜欢对可能改变的东西进行这种计算。在 Dotty 网站上的 Peano 示例中,如果您将其切换为 Peano[A],它将停止正确匹配,但如果您添加type NAT = A
它就可以正常工作。
任何关于如何使其正确匹配的想法将不胜感激。
这是代码示例:
trait BooleanAlgebra[A] {
final type N = A
type T <: N
type F <: N
val tru: T
val fls: F
final given TypeTest[T | F, T] =
x =>
println(" => T")
if x == tru then Some(tru.asInstanceOf[x.type & T])
else None
final given TypeTest[T | F, F] =
x =>
println(" => F")
if x == fls then Some(fls.asInstanceOf[x.type & F])
else None
def normalize(value: N): T | F
final def not(value: T | F): T | F =
value match
case _: T => fls
case _: F => tru
final def and(lhs: => T | F, rhs: => T | F): T | F =
lhs match
case _: T => rhs
case _: F => fls
final def or(lhs: => T | F, rhs: => T | F): T | F =
lhs match
case _: T => tru
case _: F => rhs
extension (lhs: => T | F) {
final def unary_! : T | F =
not(lhs)
final def |(rhs: => T | F): T | F =
or(lhs, rhs)
final def &(rhs: => T | F): T | F =
and(lhs, rhs)
}
}
object BooleanAlgebra {
def tru[A](using b: BooleanAlgebra[A]): b.T =
b.tru
def fls[A](using b: BooleanAlgebra[A]): b.F =
b.fls
def not[A](using b: BooleanAlgebra[A]): b.T | b.F => b.T | b.F =
value =>
b.not(value)
def norm[A](value: A)(using b: BooleanAlgebra[A]): b.T | b.F =
b.normalize(value)
}
示例实现
given BooleanAlgebra[Int] with {
type T = 1
type F = 0
val tru = 1
val fls = 0
def normalize(value: Int) =
if value > 0 then tru
else fls
}
解决方案
使用以下代码,我没有收到 scala 3.0.2 的任何警告(而且我收到了3.0.0的警告):...
我必须进行一些小的修改,首先是在我定义N
为的特征中T | F
,并在任何地方使用它:
trait BooleanAlgebra [A]:
type T <: A
type F <: A
type N = T | F
val tru: T
val fls: F
final given TypeTest [N, T] =
x =>
print ("=> T ")
if x == tru then
Some (tru.asInstanceOf [x.type & T])
else
None
final given TypeTest [N, F] =
x =>
print ("=> F ")
if x == fls then
Some (fls.asInstanceOf [x.type & F])
else
None
def normalize (value: A): N
final def not (v1: => N): N =
v1 match
case _: T => fls
case _: F => tru
final def and (v1: => N, v2: => N): N =
v1 match
case _: T => v2
case _: F => fls
final def or (v1: => N, v2: => N): N =
v1 match
case _: T => tru
case _: F => v2
然后,我以稍微不同的方式在对象中定义了扩展(因此将它们从特征中移出)(必须更改名称|
并&
阻止对现有函数的调用Int
)。同样在对象中,我定义not
了(你有)and
和or
函数(尽管测试不需要它们):
object BooleanAlgebra:
def tru [A] (using b: BooleanAlgebra [A]): b.T =
b.tru
def fls [A] (using b: BooleanAlgebra [A]): b.F =
b.fls
def norm [A] (value: A) (using b: BooleanAlgebra [A]): b.N =
b.normalize (value)
extension [A] (using b: BooleanAlgebra [A]) (v1: => b.N)
{
final def unary_! : b.N =
b.not (v1)
final def &&& (v2: => b.N): b.N =
b.and (v1, v2)
final def ||| (v2: => b.N): b.N =
b.or (v1, v2)
}
def not [A] (using b: BooleanAlgebra [A]): b.N => b.N =
v1 => b.not (v1)
def and [A] (using b: BooleanAlgebra [A]): (b.N, b.N) => b.N =
(v1, v2) => b.and (v1, v2)
def or [A] (using b: BooleanAlgebra [A]): (b.N, b.N) => b.N =
(v1, v2) => b.or (v1, v2)
示例用法,有:...
given BooleanAlgebra [Int] with
type T = 1
type F = 0
val tru = 1
val fls = 0
def normalize (value: Int): N =
if (value > 0) then 1 else 0
例如,我可以做这样的事情(关于TypeTest
代码内使用的评论):...
def test () (using ba: BooleanAlgebra [Int]): Unit =
import ba._
val a1 = 4
val n1 = normalize (a1)
// this will print normalized value of 1
println (n1)
// following not call will make a single type test for T
val n2 = !n1
println (n2)
// following two calls will make 1 type test each, for T only
println (n1 &&& n2)
println (n1 ||| n2)
// following two calls will make 2 type tests each, both for T (failing) and then F
println (n2 &&& n1)
println (n2 ||| n1)
推荐阅读
- post - 如何从提交后脚本中找到工作副本
- primefaces - 命令按钮在子节点中不起作用
- c - 为什么以下程序在获取数组中的输入后停止工作?
- javascript - 为实时更改的输入选择保持值
- javascript - SCORM 和 JavaScript:如何使 Web 应用程序与 SCORM 兼容?
- angular - Angular5服务获取自定义查询字符串参数
- powershell - 从字符串中提取多个值
- excel - VBA Excel 反透视表/提取特定数据
- sql - 合并两个表需要 SQL 帮助
- amazon-rds - 如何解决连接 AWS-RDS MYSQL 的错误(10060)?