Sml 在Trie中插入值

Sml 在Trie中插入值,sml,Sml,我在SML目录中找到了Trie的这个实现: signature DICT = sig type key = string (* concrete type *) type 'a entry = key * 'a (* concrete type *) type 'a dict (* abstract type *) val empty :

我在SML目录中找到了Trie的这个实现:

    signature DICT =
    sig
      type key = string                 (* concrete type *)
      type 'a entry = key * 'a          (* concrete type *)

      type 'a dict                      (* abstract type *)

      val empty : 'a dict
      val lookup : 'a dict -> key -> 'a option
      val insert : 'a dict * 'a entry -> 'a dict
      val toString : ('a -> string) -> 'a dict -> string
    end;  (* signature DICT *)

    exception InvariantViolationException

    structure Trie :> DICT = 
    struct
      type key = string
      type 'a entry = key * 'a

      datatype 'a trie = 
        Root of 'a option * 'a trie list
      | Node of 'a option * char * 'a trie list

type 'a dict = 'a trie

  val empty = Root(NONE, nil)

  (* val lookup: 'a dict -> key -> 'a option *)
  fun lookup trie key =
    let
      (* val lookupList: 'a trie list * char list -> 'a option *)
      fun lookupList (nil, _) = NONE
        | lookupList (_, nil) = raise InvariantViolationException
        | lookupList ((trie as Node(_, letter', _))::lst, key as letter::rest) =
            if letter = letter' then lookup' (trie, rest)
            else lookupList (lst, key)
        | lookupList (_, _) =
            raise InvariantViolationException

      (*
        val lookup': 'a trie -> char list
      *)
      and lookup' (Root(elem, _), nil) = elem
        | lookup' (Root(_, lst), key) = lookupList (lst, key)
        | lookup' (Node(elem, _, _), nil) = elem
        | lookup' (Node(elem, letter, lst), key) = lookupList (lst, key)
    in
      lookup' (trie, explode key)
    end

  (*
    val insert: 'a dict * 'a entry -> 'a dict
  *)
  fun insert (trie, (key, value)) = 
    let
      (*
        val insertChild: 'a trie list * key * value -> 'a trie list
        Searches a list of tries to insert the value. If a matching letter 
        prefix is found, it peels of a letter from the key and calls insert'. 
        If no matching letter prefix is found, a new trie is added to the list.
        Invariants:
          * key is never nil.
          * The trie list does not contain a Root.
        Effects: none
      *)
      fun insertChild (nil, letter::nil, value) = 
            [ Node(SOME(value), letter, nil) ]
        | insertChild (nil, letter::rest, value) = 
            [ Node(NONE, letter, insertChild (nil, rest, value)) ]
        | insertChild ((trie as Node(_, letter', _))::lst, key as letter::rest, value) = 
            if letter = letter' then
              insert' (trie, rest, value) :: lst
            else
              trie :: insertChild (lst, key, value)
        | insertChild (Root(_,_)::lst, letter::rest, value) =
            raise InvariantViolationException
        | insertChild (_, nil, _) = (* invariant: key is never nil *)
            raise InvariantViolationException

      (*
        val insert': 'a trie * char list * 'a -> 'a trie
        Invariants:
          * The value is on the current branch, including potentially the current node we're on.
          * If the key is nil, assumes the current node is the destination.
        Effects: none
      *)
      and insert' (Root(_, lst), nil, value) = Root(SOME(value), lst)
        | insert' (Root(elem, lst), key, value) = Root(elem, insertChild (lst, key, value))
        | insert' (Node(_, letter, lst), nil, value) = Node(SOME(value), letter, lst)
        | insert' (Node(elem, letter, lst), key, value) = Node(elem, letter, insertChild (lst, key, value))
    in
      insert'(trie, explode key, value)
    end

    (*
      val toString: ('a -> string) -> 'a dict -> string
    *)
    fun toString f trie =
      let
        val prefix = "digraph trie {\nnode [shape = circle];\n"
        val suffix = "}\n"

        (* val childNodeLetters: 'a trie list * char list -> char list *)
        fun childNodeLetters (lst, id) =
          (foldr 
            (fn (Node(_, letter, _), acc) => letter::acc
              | _ => raise InvariantViolationException) nil lst)

        (* val edgeStmt: string * string * char -> string *)
        fun edgeStmt (start, dest, lbl) =
          start ^ " -> " ^ dest ^ " [ label = " ^ Char.toString(lbl) ^ " ];\n"

        (* val allEdgesFrom: char list * char list *)
        fun allEdgesFrom (start, lst) = 
          (foldr 
            (fn (letter, acc) => 
              acc ^ edgeStmt(implode(start), implode(start @ [letter]), letter))
            "" lst)

        (* val labelNode: stirng * string -> string *)
        fun labelNode (id: string, lbl: string) =
          id ^ " [ label = \"" ^ lbl ^ "\" ];\n"

        fun toString' (Root(elem, lst), id) =
              let
                val idStr = implode(id)
                val childLetters = childNodeLetters(lst, id)
                val childStr = foldr (fn (trie, acc) => acc ^ toString'(trie, id)) "" lst
              in
                (case elem
                  of SOME(value) => 
                      labelNode (idStr, f(value)) ^ 
                      allEdgesFrom (id, childLetters)
                   | NONE => 
                      labelNode (idStr, "") ^ 
                      allEdgesFrom (id, childLetters)) ^ childStr
              end
          | toString' (Node(elem, letter, lst), id) =
              let
                val thisId = id @ [letter]
                val idStr = implode(thisId)
                val childLetters = childNodeLetters(lst, thisId)
                val childStr = foldr (fn (trie, acc) => acc ^ toString'(trie, thisId)) "" lst
              in
                (case elem
                  of SOME(value) => 
                      labelNode (idStr, f(value)) ^ 
                      allEdgesFrom (thisId, childLetters)
                   | NONE => 
                      labelNode (idStr, "") ^ 
                      allEdgesFrom (thisId, childLetters)) ^ childStr
              end
      in
        prefix ^ (toString' (trie, [#"_", #"R"])) ^ suffix
      end
end
每当我尝试使用上述函数插入或查找此实现中的字符串时:insert,lookup我都会遇到以下错误:

stdIn:1.2-1.8 Error: unbound variable or constructor: lookup
stdIn:1.2-1.8 Error: unbound variable or constructor: insert
我认为这是一个声明问题,但我不知道如何解决它。
为什么会发生这种情况?我如何在Trie数据结构中正确插入或搜索?

首先,如果您没有此代码的知识产权,您应该链接到找到它的位置,而不是重复它,因为您没有提供属性。其次,代码似乎运行良好。在这里,我插入两个键并查找它们:

$sml trie.sml
新泽西州v110.79标准毫升[建成日期:2017年8月8日星期二23:21:20]
[打开trie.sml]
签名口述=
信号
类型键=字符串
键入“a条目=键*”a
键入一个dict
val empty:“一条格言
val查找:“一个dict->key->”一个选项
val insert:'a dict*'a entry->'a dict
val-toString:('a->string)->'a dict->string
结束
[自动加载]
[库$SMLNJ-BASIS/BASIS.cm稳定]
[库$SMLNJ-BASIS/(BASIS.cm):BASIS-common.cm稳定]
[自动加载完成]
异常不变量ViolationException异常
结构Trie:DICT
-val foo=Trie.insert(Trie.empty,(“foo”,42));
val foo=-:int Trie.dict
-val bar=Trie.insert(foo,(“fab”,43));
val bar=-:int Trie.dict
-Trie.lookup条“foo”;
val it=大约42:int选项
-Trie.lookup条“fab”;
val it=大约43:int选项
-Trie.查找栏“wat”;
val it=NONE:int选项

我已投票结束此问题,因为您指出您找到了此代码,但没有将其归为属性,而且问题的根源是尚未发布的代码。您遗漏了如何使用它的详细信息。(我想你可能想读一下你最喜欢的SML书中关于结构的章节。)