- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在读这个OCaml walking through幻灯片,我在这里发现了一个有趣的问题:
看来 oops 函数会产生一个编译错误:
the type of this expression contains type variables that cannot be generalized
我不知道原因,所以我在我的 Mac 上使用 OCaml 版本 4.01.0 快速对该函数进行了一些测试,令我惊讶的是,我在解释这段代码时没有看到任何错误
我不知道为什么幻灯片声称这是一个错误,因为柯里化(Currying),我不能重新创建这个错误...
谁能帮帮我?
最佳答案
编译器提示这个错误,但顶层没有。
$ cat ungen.ml
open List
let oops = fold_left (fun a _ -> a + 1) 0
$ ocamlc -c ungen.ml
File "ungen.ml", line 2, characters 11-41:
Error: The type of this expression, '_a list -> int,
contains type variables that cannot be generalized
问题仍然存在于顶层;如果你尝试使用 oops
你会看到它计算两个不同类型列表的长度:
$ ocaml
OCaml version 4.01.0
# open List;;
# let oops = fold_left (fun a _ -> a + 1) 0;;
val oops : '_a list -> int = <fun>
# oops [1;2;3;4];;
- : int = 4
# oops ['a';'b';'c'];;
Error: This expression has type char but an expression was expected of type
int
#
请注意,如果您使用 oops
只有一种类型的列表(不是零或两个),没有错误。如果您使用 oops
,编译器可能会报错(导出的符号)零次因为它可以看到整个模块并且知道如何 oops
用来。顶层不能提示零使用,因为它永远不知道你接下来会输入什么。
更新
抱歉,我应该更多地说明实际错误是什么(在我理解的层面上)。在我看来,这与柯里化(Currying)没什么关系。
这就是臭名昭著的“值(value)限制”。值限制的简短描述如下:有些表达式不能安全地泛化。也就是说,您不能使它们成为多态的,从而允许它们与所有类型一起使用。最简单的例子是这样的:
let mylist = ref []
如果你允许mylist
具有类型 'a list ref
,然后您可以在其中存储所有不同类型的列表,这是不安全的。
但是,这可以安全地概括为:
let mylist2 = []
泛化没有问题mylist2
到类型 'a list
.
在像 OCaml 这样的现代 ML 衍生产品中,对泛化的限制已经减少到或多或少的简单规则。可以概括“值”(如 []
)。不是值的表达式(如 ref []
)不能被泛化。
表达式:
fold_left (fun a _ -> a + 1) 0
不是一个值。这是一个函数应用程序,具有与 ref []
相同的粗略形式。 .这(显然)是 oops
的定义以上。
另一方面,表达式:
fun xs -> fold_left (fun a _ -> a + 1) 0 xs
是一个值;这是一个 lambda 。所以可以泛化。这(在展开一个方便的语法缩写之后)是 len
的定义。多于。这就是为什么 len
适用于所有列表,但 oops
没那么有用。
值和非值之间的区别是语法上的;也就是说,它可以通过局部查看表达式的形式来确定。您无需了解有关表达式的类型或含义的任何信息即可做出决定。
在当前形式中使用值限制的一个论点是,在大多数情况下,您可以通过以 len
的形式定义函数来恢复所需的泛化(即多态性)。而不是 oops
的形式.这种简单的转换称为“eta 扩展”。
eta 扩展仅更改语法而不更改函数的含义这一事实表明值限制只是一个近似值。也就是说,它禁止泛化一些可以安全泛化的表达式。但它既好又简单,并且对实际程序中出现的情况没有太多限制。
从 OCaml 3.07 开始,OCaml 的值限制在基本 ML 的基础上得到了改进,因为它允许在更多情况下进行泛化。您可以在这里阅读:J. Garrigue, Relaxing the Value Restriction .本文还包含对值(value)限制及其历史的精彩总结。
关于ocaml - 为什么 "currying"要求很重要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23178233/
export const postMoviePopular = url = dispatch => { const data = axios.get(url); dispatch(sa
我一直在学习 Haskell 中的柯里化(Currying),现在尝试以柯里化(Currying)形式编写函数的 Haskell 类型签名,其非柯里化(Currying)形式有一个 (x, y) 类型
在许多列表处理语言(以及其他语言)中,它们都有一个名为 curry 的函数,它可以完成一些巧妙的事情。我的问题是为什么他们称之为 curry ?这个名字从何而来?我唯一的猜测是来自世界各国的美味 cu
当前的 curry 函数采用接受 2 个元素的元组的函数,并允许对结果函数进行 curry 或部分应用。 let x = curry (\(x, y) -> x + y) x 1 2 -- 3 是否可
假设我有 library(functional) f = function(x, p) { x^p } f2 = Curry(f, p=2) 有没有办法找出仅给定 f2 的 p 被设置为什么? 最佳答
我试图了解柯里化(Currying)相对于 Scala 中部分应用程序的优势。请考虑以下代码: def sum(f: Int => Int) = (a: Int, b: Int) => f(a)
我有一个函数,我必须包装另一个函数(如果它存在)或替换它(如果它不存在)。这意味着参数的数量会根据情况而变化。 这就是我的意思- 列列表: const myColumns = [ {name:
我不明白为什么在无类型的 lambda 演算中允许以下 beta 减少: (λx.x y) (u v) -> ((u v) y) 具体来说,我无法理解如何传递两个参数 u和 v到单个参数 x在 λx.
Ruby 1.9's built in support of currying支持两种处理带有任意数量参数的过程的方法: my_proc = proc {|*x| x.max } 1) curry 没
根据下面的代码片段,example-func-A 和 example-func-B 之间是否存在任何有意义的区别? #lang racket/base (require (only-in racket
我是 JavaScript 的新手,试图理解 Oreilly JavaScript Cookbook 中有关柯里化(Currying)的教程。 谁能用通俗易懂的语言逐步详细解释这个程序。请务必解释在程
所以我知道你可以: > f = map (+1) > f [1,2,3] [2,3,4] 但是,如果您这样做会怎样: > g = map (+) [1,2,3] > :t g g :: Num a =
我在多篇文章和博客中看到过对柯里化(Currying)函数的引用,但我找不到一个好的解释(或者至少是一个有意义的解释!) 最佳答案 柯里化(Currying)是指将一个接受多个参数的函数分解为一系列函
所以我在我们的教科书中经过一些反复试验和研究后得到了以下功能,我可以想出一个解决方案。 def prodC1(f : Int => Int) : (Int, Int) => Int = { def
我有问题,可以简化为以下示例: let func a b c = printf "%s %s %s" a b c let partial = func "a" let something_that_r
今天开始学习 Scala,我很好奇你是否可以重载一个函数来添加柯里化(Currying),比如: def add(x: Int, y: Int): Int = x + y def add(x: Int
我正在尝试编写柯里化(Currying)函数的策略,包括通用量化函数。 Require Import Coq.Program.Tactics. Definition curry1 := forall
我想以某种方式组合函数。请在伪代码(不是 F#)中考虑这两个函数 F1 = x + y F2 = F1 * 10 // note I did not specify arguments for F1,
在 Perl 6 世界中,currying 是表示部分实例化的通用术语,它也用于 (parametrized) roles 的世界。 . 但是,尚不清楚如何实际使用它: role Zipi[::T]
我想知道是否可以在多参数组函数上使用柯里化(Currying): scala> def sum(a: Int)(b: Int): Int = { a+b } sum: (a: Int)(b: Int)
我是一名优秀的程序员,十分优秀!