如何在sml中部分实现功能

如何在sml中部分实现功能,sml,ml,Sml,Ml,我正在阅读《用ML实现现代编译器》一书,同时学习sml 我被第一章中的一个练习(1.1.b)难住了。 我们被要求实现一个二叉树来维护键/值对, 键是字符串,值是参数化类型。 我的数据类型定义如下 type key=string 数据类型'a tree=LEAF | tree的树'a tree*key*'a*'树 我们被要求实现一个查找函数,其类型是'a tree*key->'a。 我不知道如何实现这个函数,因为我不知道当树是叶时返回什么。没有默认值'a。书中的说明没有说明如果找不到键该怎么办,

我正在阅读《用ML实现现代编译器》一书,同时学习sml

我被第一章中的一个练习(1.1.b)难住了。 我们被要求实现一个二叉树来维护键/值对, 键是字符串,值是参数化类型。 我的数据类型定义如下

type key=string
数据类型'a tree=LEAF | tree的树'a tree*key*'a*'树
我们被要求实现一个
查找
函数,其类型是
'a tree*key->'a
。 我不知道如何实现这个函数,因为我不知道当树是
叶时返回什么。没有默认值
'a
。书中的说明没有说明如果找不到键该怎么办,但它坚持函数必须返回type
'a

这只是书中的一个错误,还是在sml中有正确的方法可以做到这一点

在本例中,我曾尝试引发异常,但编译器显然不允许我在未捕获异常的情况下引发异常

如果我是在Scala中实现的,我会将返回类型更改为
选项[A]
,如果找不到键,则返回
None
;或者在Common Lisp中,我会用找到的值传递一个continuation调用,然后如果找不到键,就不调用continuation

这是我的代码,它还没有工作

(*第12页,练习1.1b*)
类型键=字符串
数据类型'a tree=LEAF | tree的树'a tree*key*'a*'树
val empty=LEAF
有趣的插入(键,值,叶)=树(叶,键,值,叶)
|插入(键、值、树(l、k、v、r))=
如果钥匙
然后是树(l,k,v,insert(key,value,r))
else树(l、键、值、r)
有趣的查找(叶,键)=(*!!!帮助!!!我不知道在这种情况下该怎么办*)
|查找(树(l,k,v,r),键)=如果k=键
然后v

否则,如果按键,您肯定可以更改
查找
以使用
'a选项

下面是一个基本的字典实现,它使用不透明的模块和类型参数,而不是模块参数。您派生的示例使用了一种混合,其中
是一个模块参数,
'a
作为值仍然是多态的。这通常是一个好主意,因为您在实现方面有更多的灵活性。但是,由于您只是将列表用作字典,因此可以使用
“key
来表示一个类型参数,该类型参数在相等性方面具有可比性。(如果您想要更高效的表示,如树或哈希映射,则需要更大的接口。)

现在,


顺便说一句,我不明白为什么emacs sml模式坚持缩进对查找的调用

这是因为sml模式认为
是表达式运算符,而不是声明分隔符。我在这里放置了一个
X
,如果它是表达式操作符,那么在这里放置表达式是很自然的。在创建换行符时,将后续表达式放置在同一缩进点上是很自然的

Emacs sml模式仅使用前一行来确定缩进级别,这使其变得有些简单。您可以通过在所有声明前面加上
val=,或通过放置
以不太随意的方式,例如

...
val t3 = insert ("b", 3, t2)
val L1 = lookup(t3,"a")
val L2 = ...


背后的理念s,因此,因为
s不需要终止
val…
声明,这些行不容易在声明前后更改上下文,就像
val x=…
一样。这种风格只有在您仅将SML代码作为脚本/在REPL中进行评估时才有意义。否则,如果您只对副作用感兴趣,您可能需要命名绑定或使用
val=…

这只是一个基本的实践练习;让它以不匹配的模式失败。re:“让它以不匹配的模式失败”?我明白了,错误消息只是来自我的测试用例
查找(t3,“d”)
,而不是来自编译器。好的,谢谢,我相信我理解了。如果你真的想让返回类型
'a
不引发异常,你可以永远循环:)。尽管如您所建议的,我可能会在实践中使用选项类型。我的一个想法是你的
,如果
链被
字符串上的大小写代替可能会更好。相反,比较(k,键)
- val demo = Dict.lookup "foo" (Dict.insert "foo" 42 Dict.empty)
> val demo = SOME 42 : int option
val t1 = insert("a",1,empty)
val t2 = insert("c",2,t1)
val t3 = insert("b",3,t2)
   ; X

     lookup(t3,"a");
     lookup(t3,"b");
     lookup(t3,"c");
     lookup(t3,"d");
...
val t3 = insert ("b", 3, t2)
val L1 = lookup(t3,"a")
val L2 = ...
...
val t3 = insert ("b", 3, t2)
;lookup(t3,"a");
;lookup(t3,"b");