- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 Haskell 中,函数始终采用一个参数。多个参数通过 Currying 实现。既然如此,我可以看到下面如何将两个参数的函数定义为“func1”。它是一个返回函数(闭包)的函数,该函数将外部函数的单个参数添加到返回函数的单个参数中。
然而,尽管这就是柯里化(Currying)函数的工作方式,但这并不是定义二参数函数的常规 Haskell 语法。相反,我们被教导定义这样一个函数,如“func2”。
我想知道 Haskell 如何理解 func2 的行为应该与 func1 相同。 func2 的定义中没有任何内容表明它是一个返回函数的函数。相反,它实际上看起来像一个双参数函数,我们被告知的东西不存在!
这里有什么技巧吗? Haskell 是不是一出生就知道我们可以用教科书上的方式定义多参数函数,并且它们无论如何都会按照我们期望的方式工作?也就是说,这是一个似乎没有明确记录的语法约定(Haskell 知道你的意思,并将为你提供缺少的函数返回),还是还有其他一些魔法在起作用,或者我缺少什么?
func1 :: Int -> (Int -> Int)
func1 x = (\y -> x + y)
func2 :: Int -> Int -> Int
func2 x y = x + y
main = do
print (func1 7 9)
print (func2 7 9)
最佳答案
在语言本身中,编写f x y z = _
形式的函数定义相当于f =\x y z -> _
,相当于f =\x ->\y ->\z -> _
。这没有任何理论上的理由;只是那些嵌套的 lambda 抽象令人眼花缭乱,每个人都认为牺牲一点学究气来为其制作一些语法糖就好了。这就是表面上的全部内容,并且可能是您目前需要了解的全部内容。
但是,在该语言的实现中,事情变得更加棘手。在最常见的实现 GHC 中,f x y = _
和 f =\x ->\y -> _
之间实际上是有区别的。当 GHC 编译 Haskell 时,它会为声明分配元数。 f
的前一个定义的元数为 2
,后者的元数为 0
。从 GHC.Base
(.)
(.) f g = \x -> f (g x)
(.)
具有元数 2
,即使其类型为 ((b -> c) -> (a -> b) -> a -> c
) 表示最多可以应用三次。这会影响优化:GHC 只会内联一个饱和的函数,或者至少应用了与其参数数量一样多的参数。在调用 (maximum .)
时,(.)
不会内联,因为它只有一个参数(它是不饱和)。在调用 (maximum . f)
中,它将内联到 \x -> maximum (f x)
,并且在 (maximum .f) 1
,(.)
将首先内联到 lambda 抽象(生成 (\x -> Maximum (f x)) 1
),其中将 beta-reduce 至最大值 (f 1)
。如果(.)
被实现
(.) f g x = f (g x)
(.)
的数量为 3
,这意味着它内联的频率会降低(特别是 f . g
情况,这是一个对于高阶函数来说非常常见的论点),可能会降低性能,这正是它的评论所说的:
Make sure it has TWO args only on the left, so that it inlineswhen applied to two functions, even if there is no final argument
最终答案:根据语言的语义,这两种形式应该是等价的,但在 GHC 中,这两种形式在优化方面具有不同的特征,即使它们总是给出相同的结果。
关于haskell - Haskell "understand"柯里化(Currying)函数定义吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47142209/
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)
我是一名优秀的程序员,十分优秀!