Skip to content

Instantly share code, notes, and snippets.

@mavnn
Last active May 22, 2017 10:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mavnn/b8129dc17ad276520a58d16a1a9d28ac to your computer and use it in GitHub Desktop.
Save mavnn/b8129dc17ad276520a58d16a1a9d28ac to your computer and use it in GitHub Desktop.
A simple F# Trie with stored values
module Trie
type Trie<'item, 'value when 'item : comparison> =
| Node of ('value list) * Map<'item, Trie<'item, 'value>>
| Values of 'value list
member x.values =
match x with
| Node (v, _)
| Values v -> v
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
module Trie =
let rec create (sequences : ('item list * 'value) list) =
match sequences with
| [] ->
Values []
| seqs ->
let ends, rest =
List.partition (fst >> List.isEmpty) seqs
let values =
List.map snd ends
match rest with
| [] -> Values values
| remaining ->
let subNodes =
remaining
|> List.groupBy (fst >> List.head)
|> List.map (fun (key, arr) ->
key, create (List.map (fun (items, value) -> List.tail items, value) arr))
|> Map
Node (List.map snd ends, subNodes)
let potential next trie =
match trie with
| Values v ->
None
| Node (_, subNodes) ->
Map.tryFind next subNodes
let retrieve keys trie =
let arr = Seq.toList keys
let rec inner node items =
match node, items with
| Values v, []
| Node (v, _), [] ->
v
| Values _, h::t ->
[]
| Node (_, subNodes), h::t ->
match Map.tryFind h subNodes with
| Some subNode ->
inner subNode t
| None ->
[]
inner trie arr
let exists keys trie =
match retrieve keys trie with
| [] -> false
| _ -> true
let values (trie : Trie<_,_>) =
trie.values
let rec add key value (trie : Trie<_,_>) =
match key, trie with
| [], Values vs ->
Values (value::vs)
| [], Node (vs, subNodes) ->
Node (value::vs, subNodes)
| h::t, Node (vs, subNodes) ->
match Map.tryFind h subNodes with
| Some existing ->
Node (vs, Map.add h (add t value existing) subNodes)
| None ->
Node (vs, Map.add h (create [t, value]) subNodes)
| h::t, Values vs ->
Node (value::vs, Map.add h (create [t, value]) Map.empty)
(*
let examples =
[ [ 'a'; 'b'; 'c' ], "abc"
[ 'a'; 'b'; 'd' ], "abd"
[ 'a'; 'b'; 'd' ], "abd2"
[ 'a'; 'b' ], "ab"
[ 'b'; 'c'; 'd' ], "bcd" ]
let t =
Trie.create examples
Trie.potential 'a' t
|> Option.bind (Trie.potential 'b')
Trie.retrieve ['a';'b'] t
Trie.retrieve ['a'] t
Trie.retrieve [] t
Trie.retrieve ['a';'b';'d'] t
Trie.retrieve ['a';'b';'e'] t
Trie.exists ['a';'b'] t
Trie.exists ['a'] t
Trie.exists [] t
Trie.exists ['a';'b';'d'] t
Trie.exists ['a';'b';'e'] t
*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment