0

我是 SML 语言的新学习者。我已经学习了 SML 语言的基础知识。但是,我在获取在 SML 中创建字典的代码时遇到了麻烦。所以,我想知道代码。

4

1 回答 1

1

您可以从为字典定义签名开始:

signature DICT =
sig
  type (''k, 'v) dict

  val empty : (''k, 'v) dict
  val insert : ''k -> 'v -> (''k, 'v) dict -> (''k, 'v) dict
  val lookup : ''k -> (''k, 'v) dict -> 'v option
end

''k一个相等类型)假设我唯一需要知道的关于键值存储的键是可以比较它是否相等,这样我就可以在查找时找到正确的键。这允许我使用O(n)插入和查找构建一个简单的基于列表的字典:

structure ListDict : DICT =
struct
  type (''k, 'v) dict = (''k * 'v) list

  val empty = []

  fun insert k v [] = [(k, v)]
    | insert k v ((k2,v2) :: rest) =
      if k = k2 then (k,v) :: rest else (k2,v2) :: insert k v rest

  fun lookup k [] = NONE
    | lookup k ((k2, v) :: rest) =
      if k = k2 then SOME v else lookup k rest
end

例如,类型级别的限制''k意味着我不能将我的字典表示为二叉搜索树,因为排序事物(小于、等于、大于)不是相等类型的属性,或者表示我的字典作为哈希表,因为查找值的哈希也不是相等类型的属性。

所以我可能会喜欢键可以被排序或散列。不幸的是,SML 没有内置的可排序或可散列的类型类,就像它具有相等类型一样。克服此限制的一种方法是更改​​接口,以便将比较或散列函数传递给模块。以下是可能看起来比较的方式:

signature ORD =
sig
  type t
  val compare : t -> t -> order
end

signature DICT =
sig
  type k
  type 'v dict

  val empty : 'v dict
  val insert : k -> 'v -> 'v dict -> 'v dict
  val lookup : k -> 'v dict -> 'v option
end

例如,这允许我编写基于二叉树的字典结构:

functor TreeDict (Ord : ORD) : DICT =
struct
  type k = Ord.t
  datatype 'v dict = Leaf | Node of k * 'v * 'v dict * 'v dict

  val empty = Leaf

  fun insert k v Leaf = Node (k, v, Leaf, Leaf)
    | insert k v (Node (k2, v2, left, right)) =
      case Ord.compare (k, k2) of
           EQ => Node (k, v, left, right)
         | LT => Node (k2, v2, insert k v left, right)
         | GT => Node (k2, v2, left, insert k v right)

  fun lookup k Leaf = NONE
    | lookup k (Node (k2, v, left, right)) =
      case Ord.compare (k, k2) of
           EQ => SOME v
         | GT => lookup k right
         | LT => lookup k left
end

缺点是我必须具体说明ORD我想要什么。

例如,键所在的基于树的字典int可以这样制作:

structure IntTreeDict = TreeDict(
  struct
    type t = int
    val compare = Int.compare
  end)
于 2019-11-20T12:16:38.973 回答