在函数表示环境中查找值

时间:2018-03-08 21:55:08

标签: sml ml mosml

当在bst env中找到一个值时,我所要做的就是将我要查找的值与节点上的根值进行比较

type 'a tenv = (name * 'a) btree

exception NotFound of name
fun find compare name Leaf = raise NotFound name 
| find compare name (Node (lt, (key, value), rt)) = 
  case compare(name, key) of
    LESS => find compare name lt
  | GREATER => find compare name rt
  | EQUAL => value

但是在一个代表env而不是带有节点和叶子的bst的函数中,find函数的类型为

name * 'a fenv -> 'a

type 'a fenv = name -> 'a

我对函数有了一般的了解,但我对如何遍历环境寻找名称感到困惑。 Bst有一个节点和一个像树一样的结构。如果可能,有人可以给出解释吗?

编辑

我的工作实施就是这样

exception NotFound of name
val Empty = fn name => raise NotFound name

fun Find(name, env) = env name

fun Bind(name, data, rho) = fn key => if key = name then data else rho 
key 

1 个答案:

答案 0 :(得分:3)

因此,环境现在表示为一个函数,它接受一个名称并在环境中返回其值或引发异常。
这个函数将是一个函数组合,你可以通过应用代表旧环境的函数来“遍历”它 (这听起来比现在复杂得多,但可能需要一段时间才能绕过它。)

您可以通过编写一个带有名称并引发异常的函数来创建空白环境:

val empty = fn n => raise NotFound n

查找事物比树查找要短得多,因为环境已经是那个函数:

fun find n env = env n

剩下的就是插入:

fun insert (key, value) env = ... what?

它必须是一个带名字的函数,因为这就是环境

fun insert (key, value) env = fn n => ... what?

如果nkey相同,则该函数应返回value

fun insert (key, value) env = fn n => if n = key then value else ... what?

n可能在其余环境中找到,因此我们应用该函数以便在那里查找:

fun insert (key, value) env = fn n => if n = key then value else env n

就像他们说的那样。

从某种意义上说,“遍历”代码已从查找功能转移到插入功能。

测试:

- val env = insert ("hi", 23) empty;
val env = fn : string -> int
- find "hi" env;
val it = 23 : int
- find "hello" env;

uncaught exception NotFound
  raised at: ...
- val env2 = insert ("hello", 999) env;
val env2 = fn : string -> int
- find "hello" env2;
val it = 999 : int
- find "hi" env2;
val it = 23 : int

如您所见,将事物表示为函数可以非常紧凑。

为了看看发生了什么,让我们展开第一个例子:

val env = insert ("hi", 23) empty

与(扩展insert的定义)相同:

val env = fn n => if n = "hi" then 23 else empty n

成功查找:

find "hi" env

env "hi"

(fn n => if n = "hi" then 23 else empty n) "hi"
->
if "hi" = "hi" then 23 else empty n
-> 
23

失败:

find "hello" env
->
(fn n => if n = "hi" then 23 else empty n) "hello"
->
if "hello" = "hi" then 23 else empty "hello"
->
empty "hello"
->
raise NotFound "hello"

异常处理示例:

如果您不处理异常,您将收到“未捕获的异常”错误,如上例所示。

您需要在使用find的代码中处理异常 一个简单的例子:

fun contains n env = let val _ = find n env
                     in true
                     end
                     handle NotFound nm => false


- contains "hello" env;
val it = false : bool
- contains "hi" env;
val it = true : bool