自从我编写 OCaml 代码以来已经有一段时间了,我遇到了这个听起来很简单但我无法解决的问题:
编写一个函数,该函数接受一个函数 f,该函数具有可变数量的参数并返回一个 bool 值(即 f 的类型为 'a -> ' b -> 'c -> ... -> bool) 并返回一个函数 g 表示 f 的否定(即 (f x1 x2 .. xn) == not (g x1 x2 .. xn) 对于所有有效参数集。
它受到以下代码块的启发,该代码块解决了 Javascript 中的问题:
function negate(func) {
return function() {
return !func.apply(null, arguments);
};
}
(来自 http://eloquentjavascript.net/1st_edition/chapter6.html)
但是,我没有看到在 OCaml 中实现它的方法(“arguments”关键字或等效关键字不可用),因为函数 f 没有预设数量的参数.我找到了有关处理参数数量可变的函数(例如 https://blogs.janestreet.com/variable-argument-functions/ )的链接,但我想知道是否有更简单/更“自然”的方法来处理这个特定问题。
最佳答案
我是一名 JavaScript 程序员,我一直认为 variadic arguments are harmful .如果我们在 JavaScript 中没有可变参数函数(只要远离 arguments 对象),那么在 Hindley Milner 类型系统中可键入的每个 JavaScript 函数(减去 API 特定函数,如 DOM 函数)都可以可以很容易地转换为 OCaml 中的等效函数。
那么 apply 函数在 OCaml 中的等价物是什么?我相信这是正常的功能应用程序:
let apply f x = f x (* equivalent of apply in JavaScript *)
普通的函数应用如何等同于 JavaScript 中的 apply 函数?考虑:
let s f g x = f x (g x) (* the S combinator from the SKI combinator calculus *)
这个函数将用 JavaScript 编写如下:
var s = function (f) {
return function (g) {
return function (x) {
return f(x)(g(x));
};
};
};
请注意,每个函数定义和函数调用都是以柯里化(Currying)形式显式编写的。
这是 JavaScript 和 OCaml 的区别:
那么,让我们看一下 S 组合器的非柯里化(Currying)变体。首先,OCaml:
let s (f, g, x) = f (x, g (x)) (* sml convention is to use uncurried functions *)
JavaScript 中的等价物:
var s = function (f, g, x) {
return f(x, g(x));
};
请注意,正常的函数应用在 OCaml 和 JavaScript 中是相同的。对于柯里化(Currying)函数:
let result = s f g x (* equivalent to `((s f) g) x` *)
JavaScript 中的等价物:
var result = s(f)(g)(x);
对于非柯里化(Currying)函数:
let result = s (f, g, x)
JavaScript 中的等价物:
var result = s(f, g, x);
那么 apply 函数呢?这与正常的功能应用程序有何等同?
在 OCaml 中,您可以这样做:
let args = (f, g, x) (* args is a tuple *)
let result = s args (* normal function application *)
JavaScript 中的等价物是:
var args = [f, g, x]; // args is an array
var result = s.apply(null, args); // normal function application
如您所见,OCaml 中的元组等同于 JavaScript 中的数组。 JavaScript 中的数组用途广泛。它们可以用作列表或元组,具体取决于上下文。
apply 的args 参数可以是任何类似数组的对象,它被视为单个元组参数。 JavaScript 中的每个函数都可以被认为是一个单参数函数。 JavaScript 中的多参数函数可以被认为是单参数元组参数函数。 JavaScript的apply函数只是普通函数应用的一种特殊形式。
那么这意味着什么呢?考虑:
var negate = function (f) {
return function () {
return !f.apply(null, arguments);
};
};
如果我们将 arguments 视为内部函数的隐式参数,则 OCaml 中上述函数的等价物为:
let negate f = fun arguments -> not (f arguments) (* arguments is explicit *)
这可以简化为:
let negate f x = not (f x)
现在,您可能会说这只适用于单参数函数。事实并非如此。 negate 的类型签名是:
val negate : ('a -> bool) -> 'a -> bool
因此,它适用于任何类型的 'a,包括元组。这相当于 JavaScript 中的多参数函数只是单参数元组参数函数。
最后,唯一真正的问题是将柯里化(Currying)函数转换为非柯里化(Currying)函数,以便您可以否定它们。不幸的是,在 OCaml 中没有取消函数化的通用方法。因此,您需要一系列函数来 uncurry 柯里化(Currying)多个参数的函数:
let uncurry2 f (x, y) = f x y
let uncurry3 f (x, y, z) = f x y z
.
.
.
.
在取反函数后,您可以curry 将它们返回。然而,就像使用 uncurry 一样,没有办法一般地 curry 一个函数。因此,您再次需要一系列 curry 函数:
let curry2 f x y = f (x, y)
let curry3 f x y z = f (x, y, z)
.
.
.
.
创建通用 curry 或 uncurry 函数的唯一方法是使用动态类型语言(如 Lisp 或 JavaScript)或依赖类型语言(如 Idris 或 Agda)。 OCaml 的类型系统(Hindley Milner 类型系统)限制太多,不允许这样的函数。
关于javascript - OCaml 相当于 javascript 'apply',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30990112/
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳
我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request
似乎无法为此找到有效的答案。我正在阅读Rails教程的第10章第10.1.2节,但似乎无法使邮件程序预览正常工作。我发现处理错误的所有答案都与教程的不同部分相关,我假设我犯的错误正盯着我的脸。我已经完成并将教程中的代码复制/粘贴到相关文件中,但到目前为止,我还看不出我输入的内容与教程中的内容有什么区别。到目前为止,建议是在函数定义中添加或删除参数user,但这并没有解决问题。触发错误的url是http://localhost:3000/rails/mailers/user_mailer/account_activation.http://localhost:3000/rails/mai
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。