項目與零件之間存在隱含的關係。至少你需要將一個Item分解成Part對象,並且重構你需要做的相反。
因此,採取"hello": String
,你需要有f("hello")
回報('h': Char, "ello": String)
,你需要反函數g('h', "ello")
返回"hello"
。
因此,只要遵循一些規則,具有兩個這樣的函數的任何兩種類型都會執行。我認爲這些規則很容易理解。這或多或少地是如何使用head
和tail
遞歸地分解列表並使用::
重建它您可以使用上下文綁定爲通常類型提供這些函數。
(編輯)
其實我真的不能使用綁定因爲有兩個類型參數的情況下,但是這是我腦子裏想的:
trait R[Item, Part] {
def decompose(item: Item): (Part, Item)
def recompose(item: Item, part: Part): Item
def empty: Item
}
class NotATrie[Item, Part](item: Item)(implicit rel: R[Item, Part]) {
val brokenUp = {
def f(i: Item, acc: List[Part] = Nil): List[Part] = {
if (i == rel.empty) acc
else {
val (head, tail) = rel.decompose(i)
f(tail, head :: acc)
}
}
f(item)
}
def rebuilt = (rel.empty /: brokenUp)((acc, el) => rel.recompose(acc, el))
}
然後我們提供了一些隱含對象:
implicit object string2R extends R[String, Char] {
def decompose(item: String): (Char, String) = (item.head, item.tail)
def recompose(item: String, part: Char): String = part + item
def empty: String = ""
}
implicit object string2RAlt extends R[String, Int] {
def decompose(item: String): (Int, String) = {
val cp = item.codePointAt(0)
val index = Character.charCount(cp)
(cp, item.substring(index))
}
def recompose(item: String, part: Int): String =
new String(Character.toChars(part)) + item
def empty: String = ""
}
val nat1 = new NotATrie[String, Char]("hello")
nat1.brokenUp // List(o, l, l, e, h)
nat1.rebuilt // hello
val nat2 = new NotATrie[String, Int]("hello\ud834\udd1e")
nat2.brokenUp // List(119070, 111, 108, 108, 101, 104)
nat2.rebuilt // hello
所以這個邊界看起來像是Item {%{def decons(i:Item)=>(Part,Item)} {def cons(p:Part,i:Item)=> Item} '我知道這可能是語法錯誤,但是這是否是正確的想法? – Dylan
我根據您指出的內容進行了更改,但隱含對象的部分似乎只能通過命令行/腳本界面工作。如果我嘗試在頂層定義隱式構建器對象,編譯器會抱怨,但如果我將它包裝在頂層對象中,則無法找到隱式轉換。如果我想給用戶提供隱式的構建器而沒有任何額外的麻煩,我可以在哪裏定義它們? – Dylan
將隱式對象放入「對象R {...}」中,編譯器應該在伴隨對象內搜索隱式定義。 – huynhjl