我正在发现 Dotty,我很想提出我的算法的类型化版本。我想实现以下我可以在 JavaScript 中轻松完成的任务。它基本上是一种提取记录或数组属性的浓缩方式:
function Field(key, action) {
return {
apply(record) {
return action.apply(record[key]);
}
};
}
var Identity = { apply(record) { return record; } };
console.log(Field(3, Field("a", Identity)).apply([0, 1, 2, {a: "Hello"}]))
// Prints out "Hello"
我有一堆函数,比如我想输入的 Field。这是我到目前为止所尝试的。记录或对象被建模为结构类型{ def get(k: Key): KeyMapper[Key] }
,如果输入的类型是静态已知的,则基本上尝试静态获取字段的类型,如在这个问题中。这是我第一次成功的尝试,下面是剩下的和失败的。
trait Apply[A, B] {
def apply(a: A): B
}
case class Identity[A]() extends Apply[A, A] {
def apply(a: A) = a
}
case class Field
[Key: ClassTag,
KeyMapper[_],
Record <: { def get(k: Key): KeyMapper[Key]},
B](key: Key, subAction: Apply[KeyMapper[Key], B]) extends Apply[Record, B] {
def apply(record: Record) = subAction(record.get(key))
}
到目前为止一切顺利,它编译时没有类型错误。现在,我希望将类型定义整合为记录Key
的KeyMapper
一部分,这样我就只有两个类型参数,而不是四个,并且代码更易于维护。我尝试了以下方法:
trait Record {
type KeyMapper[T]
type Key
def apply(k: Key): KeyMapper[Key]
}
case class Field[A <: Record, U](key: A#Key, subAction: Apply[A#KeyMapper[A#Key], U]) extends Apply[A, U] {
def apply(record: A): U = subAction(record(key))
我收到以下错误::
[error] | def apply(record: A): U = subAction(record(key))
[error] | ^^^
[error] | Found: (Down.this.key : A#Key)
[error] | Required: record.Key
好的,到目前为止,除了使用 进行转换之外,我没有看到任何其他方法key
,.asInstanceOf[record.Key]
然后我收到以下错误:
[error] 43 | def apply(record: A): U = subAction(record(key.asInstanceOf[record.Key]))
[error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error] | Found: record.KeyMapper[record.Key]
[error] | Required: A#KeyMapper[A#Key]
好的,我有点失望,但我在A#KeyMapper[A#Key]
. 然后我得到错误:
[error] 42 | case class Field[A <: Record, U](key: A#Key, subAction: Apply[A#KeyMapper[A#Key], U]) extends Apply[A, U] {
[error] | ^
[error] | A is not a legal path
[error] | since it is not a concrete type
嗯,所以我读了一点,发现类型投影已被弃用并从 Dotty 中删除,所以我需要一个具体的值。这是我的下一次尝试:
trait RecordAndEdit { outer =>
type Val <: {
def get(k: outer.Key): outer.Map[k.type]
}
type Key
type Map[_]
}
class Field[U](val rOps: RecordAndEdit)(val key: rOps.Key, val subAction: Apply[rOps.Map[rOps.Key], U]) extends Apply[rOps.Val, U] {
def apply(record: rOps.Val): U = subAction(record.get(key))
}
我得到错误
[error] 35 | def apply(record: rOps.Val): U = subAction(record.get(key))
[error] | ^^^^^^^^^^^^^^^
[error] |Structural access not allowed on method get because it has a method type with inter-parameter dependencies
此时,我不明白如何解决此错误消息,因为我希望 get 方法具有取决于输入类型的返回类型。有什么线索吗?