Sometime it's so much easier to make your own diagrams. The arrow represents the "is a" relationship with labels to specify.
I left the crazy cousin "homeo" out of the family tree, cause he's just too topological.
"_"[label="∅"]
"_"->"r_"[label=" r"]
"r_"[label="re"]
"r_"->"lr_"[label=" l"]
"r_"->"ar_"[label=" a"]
"r_"->"br_"[label=" b"]
"lr_"[label="lied(*)"]
"ar_"[label="al(*)"]
"ar_"->"iar_"[label=" i"]
"iar_"[label="ize(*)"]
"br_"[label="b"]
"br_"->"obr_"[label=" o"]
"br_"->"abr_"[label=" a"]
"obr_"[label="orn(*)"]
"abr_"[label="ate(*)"]
---"r" | | ---"ea" | | | | | ---"l" | | | | | ---"r" | | ---"ock"but then blogspot mangled it, and I realized it wasn't as pretty as a graphic like the one above. I figured to myself that there MUST be a simple domain specific language for rendering simple graphs/trees based on a text. Ideally, something like this:
a -> b -> c
b -> d
should generate something like this:
data NodeType = Top|Word|NonWord
deriving (Show,Eq)
data TrieNode a = TrieNode { wordFragment :: [a],
children :: (Map.Map a (TrieNode a)),
nodeType:: NodeType } deriving (Show,Eq)
data Dot = DotPath {fid::String, tid::String} |
DotNode{dotId::String,label::String}
instance Show Dot where
show DotPath{fid=from,tid=to@(x:_)} = "\"" ++ from ++ "\""
++ "->"
++ "\"" ++ to ++ "\""
++ "[label=\" " ++ ( x : "\"]")
show DotNode{dotId=nodeId,label=outputLabel} = "\"" ++ nodeId ++ "\""
++ "[label= \"" ++ outputLabel ++ "\"]"
generateDotLabel nodeDatum = case (nodeType nodeDatum) of
Top -> "∅"
Word -> wf ++ "(*)"
NonWord -> wf
where wf = (wordFragment nodeDatum)
generateDot :: TrieNode Char -> String -> [Dot]
generateDot nodeDatum path = myDotNode : myPaths ++ myChildrensDots
where myDotNode = DotNode{dotId= path,label=(generateDotLabel nodeDatum)}
myPaths = map generatePathNode $ (Map.keys (children nodeDatum))
myChildrensDots = foldr (++) [] $
map generateChildrenDots $ (Map.assocs (children nodeDatum))
generatePathNode x = DotPath{fid=path,tid=x:path}
generateChildrenDots (k,v) = generateDot v (k:path)
generateDotPretty tree = L.intercalate "\n" $ map show $ generateDot tree "_"
testWords = ["rebate", "reborn", "realize", "real", "relied", "rebates", "reb", "relief", "realizes", "redder", "red"]
"_"[label= "∅"]
"_"->"r_"[label=" r"]
"r_"[label= "re"]
"r_"->"ar_"[label=" a"]
"r_"->"br_"[label=" b"]
"r_"->"dr_"[label=" d"]
"r_"->"lr_"[label=" l"]
"ar_"[label= "al(*)"]
"ar_"->"iar_"[label=" i"]
"iar_"[label= "ize(*)"]
"iar_"->"siar_"[label=" s"]
"siar_"[label= "s(*)"]
"br_"[label= "b(*)"]
"br_"->"abr_"[label=" a"]
"br_"->"obr_"[label=" o"]
"abr_"[label= "ate(*)"]
"abr_"->"sabr_"[label=" s"]
"sabr_"[label= "s(*)"]
"obr_"[label= "orn(*)"]
"dr_"[label= "d(*)"]
"dr_"->"ddr_"[label=" d"]
"ddr_"[label= "der(*)"]
"lr_"[label= "lie"]
"lr_"->"dlr_"[label=" d"]
"lr_"->"flr_"[label=" f"]
"dlr_"[label= "d(*)"]
"flr_"[label= "f(*)"]
data NodeType = Top|Word|NonWord
deriving (Show,Eq)
data TrieNode a = TrieNode { wordFragment :: [a],
children :: (Map.Map a (TrieNode a)),
nodeType:: NodeType } deriving (Show,Eq)
generateDot :: TrieNode Char -> String -> [Dot]
This is something I plan on revisiting as it is possible to render the 'structure' but auto-generate the labels. Gotta think about that.generateDot nodeDatum path = myDotNode : myPaths ++ myChildrensDots
generateDotPretty tree = L.intercalate "\n" $ map show $ generateDot tree "_"
data TrieNode = TrieNode { wordFragment :: String, children :: Map.Map Char TrieNode
isTop :: Bool, isWord :: Bool}
Refinement:
data NodeType = Top|Word|NonWord
deriving (Show,Eq)
data TrieNode a = TrieNode { wordFragment :: [a],
children :: (Map.Map a (TrieNode a)),
nodeType:: NodeType } deriving (Show,Eq)
data NodeType = Top|Word|NonWord
deriving (Show,Eq)
data TrieNode a = TrieNode { wordFragment :: [a],
children :: (Map.Map a (TrieNode a)),
nodeType:: NodeType } deriving (Show,Eq)
data TrieNode = TrieNode { wordFragment :: String, children :: [TrieNode]
isTop :: Bool, isWord :: Bool}
topNode = TrieNode { wordFragment ="" , children = [] , isTop = True, isWord = False}
import qualified Data.Map as Map
data TrieNode = TrieNode { wordFragment :: String, children :: Map.Map Char TrieNode
isTop :: Bool, isWord :: Bool}
if ( insertion string is prefix to target string) then "extend branch internally" where "extend branch internally" = use the target string as a new node's word-fragment, and point this new node to the old node with shortened word-fragment.
if ( insertion string and target string share prefix) then "create fork" where "create fork" = 1) use the target string shared prefix as a new node's word-fragment,
2) use the target strings suffix as a new node's word-fragment, now point #1 to this one
3) point this new node to the old node with shortened word-fragment.