如何实现字典作为OCaml中的函数?(How to implement a dictionary a

2019-08-03 13:23发布

我学习杰森-希基的介绍语言Objective Caml 。


这里是一个练习,我没有任何线索


首先,这是什么意思实现dictionary作为一个function ? 我怎样才能像呢?

我们是否需要任何array或类似的东西? 显然,我们不能在这个练习阵列,因为array尚未在介绍Chapter 3 。 但How do I do it without some storage?

所以,我不知道该怎么做,我想一些提示和指南。

Answer 1:

我认为,这项工作的关键是让你用瓶盖。 例如,考虑以下对OCaml的函数在文件fun-dict.ml

let empty (_ : string) : int = 0
let add d k v = fun k' -> if k = k' then v else d k'

然后在OCaml的提示,你可以这样做:

 # #use "fun-dict.ml";; val empty : string -> int = val add : ('a -> 'b) -> 'a -> 'b -> 'a -> 'b = # let d = add empty "foo" 10;; val d : string -> int = # d "bar";; (* Since our dictionary is a function we simply call with a string to look up a value *) - : int = 0 (* We never added "bar" so we get 0 *) # d "foo";; - : int = 10 (* We added "foo" -> 10 *) 

在这个例子中是字典上的一个功能string钥匙的int值。 该empty功能是,所有的键映射到一个字典0 。 add函数创建一个封闭这需要一个参数,一个关键。 请记住,我们的字典中的定义,这里是从功能的关键值,所以这个闭合是一本字典。 它检查以查看是否k' (闭合参数) = k其中k是刚添加的键。 如果它返回新的值,否则它会调用旧字典。

您有效地具有由封闭在链中的下一个词典(功能))的利弊细胞不通过链接关闭的名单。

额外锻炼,你会如何删除这个字典中的关键?


编辑:什么是封闭?

闭包是它引用自其创建变量的作用域(地名)的功能。那么,是什么意思呢?

考虑我们的add功能。 它返回一个函数

fun k' -> if k = k' then v else d k

如果你只看该函数有没有定义的三个名字, dk ,和v 。 为了弄清楚它们是什么,我们必须在封闭的范围看,即范围add 。 我们在那里找到

let add d k v = ...

因此,即使后add已返回功能仍引用添加参数的新功能。 所以一个封闭件是必须由一些外范围,以便封闭上是有意义的函数。



Answer 2:

在OCaml中,你可以使用真正的函数来表示一本字典。 非FP语言通常不支持函数作为第一类对象,所以如果你已经习惯了他们,你可能会遇到麻烦有这样的想法在第一。

字典一个图,这是一个功能。 想象一下,你有一个函数d ,需要一个字符串,还给了许多。 它给回不同的字符串不同的号码,但总是相同的字符串相同的号码。 这是一本字典。 该字符串是你仰视的东西,你回来的数量在字典中的相关条目。

你并不需要一个数组(或列表)。 您的add功能可以构造确实没有任何(明确的)数据结构什么是必要的功能。 需要注意的是add功能,需要一个字典(功能)并返回一个字典(新功能)。

要开始思考高阶函数,这里是一个例子。 该函数bump接受一个函数( f: int -> int )和int( k: int )。 它返回返回的值的新功能k不是什么大f对于相同的输入的回报。

let bump f k = fun n -> k + f n

(该点是bump ,像add ,取一个函数和一些数据,并返回基于这些值的新的功能。)



Answer 3:

我想这可能是值得补充的是在ocaml的功能不只是代码段(不像在C,C ++,JAVA等)。 在这些非功能性语言,功能不具有与其相关的任何状态 ,这将是一种可笑的谈论这样的事情。 但是,这不是与函数式语言功能的情况下,你应该开始把它们当作一种对象 ; 一个奇怪的一种对象,是的。

那么,如何才能“制造”这些对象呢? 让我们杰弗里的例子:

let bump f k = 
  fun n ->
    k + f n

现在是什么bump实际上做? 它可以帮助你思考的bump与您可能已经很熟悉的构造函数 。 这是什么构造? 它构造函数对象 (很losely这里讲的)。 那么什么状态这是否导致对象有? 它有两个实例变量(排序的),其是fk 。 当你调用这两个实例变量绑定到结果函数对象bump fk 。 你可以看到,返回的函数对象:

fun n ->
  k + f n

利用这些实例变量fk在它的身上。 一旦返回此函数的对象,你只能调用它,还有你访问没有其他办法fk (所以这是封装)。

这是非常罕见的使用术语函数对象 ,它们被称为只是功能 ,但你必须记住,他们可以“封闭”状态为好。 这些函数对象 (也叫闭包)被不远处的面向对象编程语言的“真实的”对象分开,一个很有趣的讨论,可以发现在这里 。



Answer 4:

我也有这个问题所困扰。 这里是我的解决方案,它适用于在课本中所列的情况下...

一个空的字典简单地返回0:

let empty (k:string) = 0

查找调用字典的上键功能。 这个功能很简单:

let find (d: string -> int) k = d k

添加扩展字典有另一个条件分支的功能。 我们返回一个新的字典,将密钥K”,并与它匹配对K(我们需要添加键)。 如果匹配,我们返回V(对应值)。 如果它不符合我们回到老(小)词典:

let add (d: string -> int) k v =
    fun k' ->
        if k' = k then
                v
            else
                d k'

你可能会改变加有一个删除功能。 另外,我加了一个条件,以确保我们不会删除非内已有的关键。 这仅仅是实践。 字典的实现是坏反正:

let remove (d: string -> int) k =
    if find d k = 0 then
        d
    else
        fun k' ->
            if k' = k then
                    0
                else
                    d k'

我不擅长用的术语,因为我仍然在学习函数式编程。 因此,随时纠正我。



文章来源: How to implement a dictionary as a function in OCaml?