我是 SML 语言的新学习者。我已经学习了 SML 语言的基础知识。但是,我在获取在 SML 中创建字典的代码时遇到了麻烦。所以,我想知道代码。
问问题
908 次
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 回答