I’m currently working on implementing my own Trie in Scala (for learning/hobby purposes), and I’m trying to keep it generic (so that it can store anything Iterable, not just Strings). My class signature looks like
class Trie[Item <% Iterable[Part], Part](items: Item*) extends Set[Item]
I already have contains, += and -= implemented (it’s extending the mutable version of Set), but I’m having some trouble with the iterator. My current approach has me scratching my head looking for a graceful implementation. I have a way to iterate over all of the TrieNodes, and give off only the ones that are marked as a “valid ending”. From there I plan to follow parent links to get the individual parts. (e.g. “hello” in the tree would be stored as an ‘o’ node marked as an ending, with parent ‘l’ -> ‘l’ -> ‘e’ -> ‘h’)
Now my problem. Since I’m trying to keep things generic I have no way to reconstruct the “Item” from its “Parts.” So my question to the people of SO is what would be the most graceful way to handle this? Should I add a reconstruction function to the constructor arguments? Should Item be bounded differently to enforce the presence of the function? Or is it something else entirely?
There is an implied relationship between Item and Part. At the minimum you need to decompose an Item into Part objects and to reconstruct you need to do the reverse.
So taking
"hello": String, you need to havef("hello")return('h': Char, "ello": String)and you need the inverse functiong('h', "ello")return"hello".So any two types with two such functions will do as long as some rules are followed. I think the rules are easy to intuit. It’s more or less how you decompose a list recursively using
headandtailand rebuild it using::You could use a context bound to provide these functions for the usual type.
(edit)
Actually I can’t really use a context bound because there are two type parameters, but this is what I had in mind:
Then we provide some implicit objects: