Function 部分应用函数
在研究函数式编程时,经常会出现部分应用函数的概念。在Haskell中,内置函数Function 部分应用函数,function,haskell,partially-applied-type,Function,Haskell,Partially Applied Type,在研究函数式编程时,经常会出现部分应用函数的概念。在Haskell中,内置函数take被认为是部分应用的 我仍然不清楚部分应用函数的确切含义,或者它的使用/含义。函数本身不能“部分应用”或不“部分应用”。这是一个毫无意义的概念 当你说一个函数是“部分应用的”时,你指的是如何调用该函数(也称为“应用的”)。如果调用该函数及其所有参数,则称其为“完全应用”。如果缺少某些参数,则该函数称为“部分应用” 例如: -- The function `take` is fully applied here:
take
被认为是部分应用的
我仍然不清楚部分应用函数的确切含义,或者它的使用/含义。函数本身不能“部分应用”或不“部分应用”。这是一个毫无意义的概念 当你说一个函数是“部分应用的”时,你指的是如何调用该函数(也称为“应用的”)。如果调用该函数及其所有参数,则称其为“完全应用”。如果缺少某些参数,则该函数称为“部分应用” 例如:
-- The function `take` is fully applied here:
oneTwoThree = take 3 [1,2,3,4,5]
-- The function `take` is partially applied here:
take10 = take 10 -- see? it's missing one last argument
-- The function `take10` is fully applied here:
oneToTen = take10 [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,42]
部分函数应用程序的结果是另一个函数-仍然“期望”获取其缺少的参数的函数-如上例中的take10
,仍然“期望”接收列表
当然,一旦你进入高阶函数,它会变得更复杂一些,也就是说,函数以其他函数作为参数,或者返回其他函数作为结果。考虑这个函数:
mkTake n = take (n+5)
(+ 5) :: Num a => a -> a
add = \x -> x + 3
函数mkTake
只有一个参数,但它返回另一个函数作为结果。现在,考虑一下:
x = mkTake 10
y = mkTake 10 [1,2,3]
在第一行,函数mkTake
显然是“完全应用的”,因为它有一个参数,这正是它所期望的参数数量。但是第二行也是有效的:因为mkTake 10
返回一个函数,所以我可以用另一个参数调用这个函数。那么,它使mkTake
成为什么呢?“过度应用”,我猜
然后考虑一个事实:(除非编译器优化)所有的函数在数学上都是一个参数的函数。这怎么可能?当您声明一个函数时,
take nl=…
,您“概念上”说的是take=\n->\l->…
——也就是说,take
是一个函数,它接受参数n
,并返回另一个接受参数l
并返回一些结果的函数
因此,底线是“部分应用程序”的概念实际上并没有严格定义,它只是一个方便的缩写,用来指那些“应该”(如常识所示)接受N个参数,但被赋予M
-- The function `take` is fully applied here:
oneTwoThree = take 3 [1,2,3,4,5]
-- The function `take` is partially applied here:
take10 = take 10 -- see? it's missing one last argument
-- The function `take10` is fully applied here:
oneToTen = take10 [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,42]
部分函数应用程序的结果是另一个函数-仍然“期望”获取其缺少的参数的函数-如上例中的take10
,仍然“期望”接收列表
当然,一旦你进入高阶函数,它会变得更复杂一些,也就是说,函数以其他函数作为参数,或者返回其他函数作为结果。考虑这个函数:
mkTake n = take (n+5)
(+ 5) :: Num a => a -> a
add = \x -> x + 3
函数mkTake
只有一个参数,但它返回另一个函数作为结果。现在,考虑一下:
x = mkTake 10
y = mkTake 10 [1,2,3]
在第一行,函数mkTake
显然是“完全应用的”,因为它有一个参数,这正是它所期望的参数数量。但是第二行也是有效的:因为mkTake 10
返回一个函数,所以我可以用另一个参数调用这个函数。那么,它使mkTake
成为什么呢?“过度应用”,我猜
然后考虑一个事实:(除非编译器优化)所有的函数在数学上都是一个参数的函数。这怎么可能?当您声明一个函数时,
take nl=…
,您“概念上”说的是take=\n->\l->…
——也就是说,take
是一个函数,它接受参数n
,并返回另一个接受参数l
并返回一些结果的函数
因此,底线是“部分应用程序”的概念实际上并没有严格定义,它只是一个方便的缩写,用来指那些“应该”(如常识所示)接受N个参数,但被赋予Madd :: Int -> Int -> Int
add x y = x + y
add
函数接受两个参数并将它们相加,现在我们可以实现了
increment = add 1
通过部分应用add
,它现在等待另一个参数。经典示例是
add :: Int -> Int -> Int
add x y = x + y
add
函数接受两个参数并将它们相加,现在我们可以实现了
increment = add 1
通过部分应用
add
,它现在等待另一个参数。通过示例可以最好地理解这一点。下面是加法运算符的类型:
(+) :: Num a => a -> a -> a
这是什么意思?如你所知,它需要两个数字并输出另一个。正当嗯,有点
你看,a->a->a实际上意味着:a->(a->a)
。哇,看起来怪怪的!这意味着(+)
是一个接受一个参数并输出一个函数(!!)的函数,该函数也接受一个参数并输出一个值
这意味着您可以将一个值提供给(+)
,以获得另一个部分应用的函数:
mkTake n = take (n+5)
(+ 5) :: Num a => a -> a
add = \x -> x + 3
此函数接受一个参数并向其添加五个参数。现在,用一些参数调用新函数:
Prelude> (+5) 3
8
给你!部分功能应用在工作中
注意(+5)3的类型:
(+5) 3 :: Num a => a
看看我们最终得到了什么:
(+)::Num a=>a->a->a
(+5)::Num a=>a->a
(+5)3::Num a=>a
您是否看到类型签名中的a
s的数量在每次添加时都会减少一个