As usual, presented as a learning exercise without warranty or implied fitness; use at your own risk. Also as usual, formatted for the blog window (I have a twin horror of code wrap and horizontal scrolling, lol.)
Main module (test code below):
module SemanticNet
open System.Collections.Generic
let internal findOrNew<'k,'v> (ff:'k->bool*'v)
(fn:unit->'v)
(fa:'k*'v->unit)
(k:'k) =
match ff k with
| (true,v) -> v
| (false,_) ->
let v = fn()
fa(k,v)
v
let internal findOrNewD<'k,'v> (d:Dictionary<'k,'v>)
(fn:unit->'v)
(k:'k) =
findOrNew d.TryGetValue fn d.Add k
let internal findOrNone<'k,'v> (ff:'k->bool*'v)
(k:'k) =
match ff k with
| (true,v) -> Some(v)
| _ -> None
let internal findOrNoneD<'k,'v> (d:Dictionary<'k,'v>)
(k:'k) =
findOrNone d.TryGetValue k
type Entity (graph:Graph, key:string) =
member this.Graph = graph
member this.Key = key
and Link (graph:Graph, key:string) =
inherit Entity(graph,key)
and LinksOut (nodeIn:Node, link:Link) =
let nodesOut = new Dictionary<string,Node>()
let newNodeOut nodeKey =
let nodeOut:Node = nodeIn.Graph.Node nodeKey
nodeOut.AddIn link.Key nodeIn
nodeOut
member this.Node (nodeOutKey:string) =
findOrNewD nodesOut
(fun()->(newNodeOut nodeOutKey))
nodeOutKey // Node
member this.Nodes (nodeOutKeys:string list) =
match nodeOutKeys with
| [] -> nodeIn.Graph
| h::t ->
this.Node h |> ignore
this.Nodes t
member this.TestWrite (p:string->unit) =
p (" "+link.Key+"\n")
for node in nodesOut.Values do
p (" "+node.Key+"\n")
static member (+) ((this:LinksOut),
(nodeKey:string)) =
(this.Node nodeKey).Graph
static member (+) ((this:LinksOut),
(nodeKeys:string list)) =
this.Nodes nodeKeys
and LinksIn (nodeOut:Node, link:Link) =
let nodesIn = new Dictionary<string,Node>()
member internal this.Node (nodeIn:Node) =
if not (nodesIn.ContainsKey nodeIn.Key) then
nodesIn.Add(nodeIn.Key,nodeIn)
and Node (graph:Graph, key:string) =
inherit Entity(graph,key)
let linksOut = new Dictionary<string,LinksOut>()
let linksIn = new Dictionary<string,LinksIn>()
member internal this.AddIn (linkInKey:string) (nodeIn:Node) =
((findOrNewD linksIn
(fun()->(graph.LinksIn this linkInKey))
linkInKey).Node nodeIn) |> ignore
member this.Link (linkOutKey:string) =
findOrNewD linksOut
(fun()->(graph.LinksOut this linkOutKey))
linkOutKey // Links
member this.Links ((linkOutKey:string),(nodeOutKeys:string list)) =
(findOrNewD linksOut
(fun()->(graph.LinksOut this linkOutKey))
linkOutKey).Nodes nodeOutKeys |> ignore
this // Node
member this.TestWrite (p:string->unit) =
p (key+"\n")
for links in linksOut.Values do
links.TestWrite p
static member (+) ((this:Node),
(linkOutKey:string)) =
this.Link linkOutKey
static member (+) ((this:Node),
(linkNodeOut:string*string list)) =
this.Links linkNodeOut
and Graph () =
let links = new Dictionary<string,Link>()
let nodes = new Dictionary<string,Node>()
member internal this.Link linkKey =
findOrNewD links
(fun()->Link(this,linkKey)) linkKey // Link
member internal this.LinksIn node linkKey =
LinksIn(node,(this.Link linkKey))
member internal this.LinksOut node linkKey =
LinksOut(node,(this.Link linkKey))
member this.Node nodeKey =
findOrNewD nodes
(fun()->Node(this,nodeKey))
nodeKey // Node
member this.TestWrite (p:string->unit) =
for node in nodes.Values do
node.TestWrite p
static member (+) ((this:Graph),(nodeKey:string)) =
this.Node nodeKey
Test code:
open System
open SemanticNet
let g = Graph()
g+"dog"+
("isA",["canine";"man's best friend";"pet"])+
("hasA",["leash";"collar"]) |> ignore
g+"mammal"+"isA"+"animal" |> ignore
g+"canine"+"isA"+"mammal" |> ignore
g+"man's best friend"+"isA"+"dog" |> ignore
g.TestWrite (fun s->Console.Write(s))
Console.ReadLine() |> ignore
No comments:
Post a Comment