如何在sml中部分实现功能
我正在阅读《用ML实现现代编译器》一书,同时学习sml 我被第一章中的一个练习(1.1.b)难住了。 我们被要求实现一个二叉树来维护键/值对, 键是字符串,值是参数化类型。 我的数据类型定义如下如何在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。书中的说明没有说明如果找不到键该怎么办,
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");