Во-первых, позвольте мне извиниться, если мой вопрос неясен. Я еще не совсем понял язык Scala, поэтому я, вероятно, объединяю термины. Я думаю, что мой пример будет более ясным.Как я могу специализировать признак с ограничением типа None?
Я пытаюсь создать признак Hierarchical
, который описывает в основном вершины в графе - любой объект, который может иметь список родителей и список детей.
Более конкретно:
1)
Hierarchical
может или не может иметь родителей.2) Если это так, то родители
Hierarchical
.3)
Hierarchical
будет иметь детей, которые такжеHierarchical
.
Вот моя общая черта:
/*
Hierarchical takes two type parameters: Parent and Child.
These should be Hierarchicals with parameters Parent and Child as well.
*/
trait Hierarchical[Parent <: Hierarchical[Parent, Child],
Child <: Hierarchical[Parent, Child]] {
// parents must be passed by constructor lest they are treated as None.
// (Requirement 1, 2)
val parents: Option[List[Hierarchical[Parent, Child]]] = None
// children can be added, so mutability needed (Requirement 3)
var children: List[Hierarchical[Parent, Child]] = List()
def addChild(child: Child) = children ++= List(child)
}
специализации на это «корень» вершина, чьи родители не будут существовать, поэтому тип не должен быть указан на всех - константы выглядит , это None
. Вот моя попытка специализировать Hierarchical
черта:
/*
A RootHierarchical has no parents. It does, however, have
children whose parents are RootHierarchicals and whose children
are Child.
A parent can be none (Requirement 1)
*/
trait RootHierarchical[Child <: Hierarchical[RootHierarchical, Child]]
extends Hierarchical[None.type, Child] {
override val parents = None
}
IntelliJ доволен этим, но тест я написал не компиляции:
import org.scalatest.FlatSpec
class TestHierarchy extends FlatSpec {
"A Hierarchical object" should "be constructable" in {
/*
Create a dummy
*/
class DummyHierarchical(override val parents: List[DummyParentHierarchical])
extends Hierarchical[DummyParentHierarchical, DummyHierarchical]
class DummyParentHierarchical extends RootHierarchical[DummyHierarchical]
val dummyParent = new DummyParentHierarchical
val dummyChild = new DummyHierarchical(List(dummyParent))
dummyParent.addChild(dummyChild)
assert(dummyParent.parents.isEmpty)
assert(dummyParent.children.nonEmpty)
}
}
Ошибка здесь:
Error:(14, 11) type arguments [None.type,Child] do not conform to trait Hierarchical's type parameter bounds [Parent <: Hierarchical[Parent,Child],Child <: Hierarchical[Parent,Child]]
extends Hierarchical[None.type, Child] {
Мой вопрос таков: как я могу создать эту специализацию? Я знаю, что None.type
не является типом Hierarchical
, но как я могу специализироваться на этом?
Я думаю, что этот вопрос, исходя из вашего определения признака. 'черта Иерархический [Родитель <: Опция [Иерархический [Родитель, Ребенок]], Child <: Иерархическая [Опция [Родитель], Ребенок]]' говорит что-то вроде этого пункта спараметрировано с типом родителя, который является вариант этого признака с теми же родительскими и дочерними типами, что и этот экземпляр, и дочерним типом, который параметризуется опцией parent (которая сама является опцией) и ее собственным типом, что означает, что родительский элемент ребенка является опцией Родитель. –
Я очень рекомендую взглянуть на разговор Роба Норриса о программировании с программированием на основе функциональных баз данных с использованием типов Fixpoint (https://www.youtube.com/watch?v=7xSfLPD6tiQ).В разговоре используется Doobie, но он действительно применим к любой рекурсивной структуре данных. –
@AngeloGenovese Спасибо за видео - очень интересно. Не уверен, что я могу использовать его, потому что он использует теорию категорий, которая в значительной степени опирается на типы. Я полагаюсь на черты; то есть родители и дети могут быть разных типов, если они оба реализуют «Иерархический». – erip