写一个lambda表达式的"curried版本"

Ste*_*eve 1 lambda haskell currying

我正在研究Haskell,并试图理解如何将currying的概念应用于函数.我理解currying本质上是一种带有多个参数的函数并将函数应用于一个参数的方法,返回一个应用于第二个函数的函数,依此类推......而不会失去任何表达性.我正在研究的一个教程问:

"写一个咖喱版2 * (\x y -> x*y)2 3"

我希望有人可以帮我告诉我如何解决这个问题.提前致谢

编辑:回应两个评论者,我可以看到认识

(\x y -> x*y) :: Num a => a -> a -> a

......是我的第一步.在功能性编程方面我的学习曲线相当缓慢(也是新的SO海报,所以我打破了任何礼仪的借口)......我的下一步是什么?

编辑2:@Mikhail,我看到uncurry应用于lambda表达式的类型会形成某种形式(给定uncurry :: (a -> b -> c) -> (a,b) -> c)

Num a => (a,a) -> a 
Run Code Online (Sandbox Code Playgroud)

Ste*_*ans 5

您对currying的基本理解是正确的.具体地说,它是关于转换一个将其参数作为元组的函数,例如

add :: (Int, Int) -> Int
add    (x, y)     =  x + y
Run Code Online (Sandbox Code Playgroud)

进入一个一次获取一个参数的函数:

add' :: Int -> Int -> Int
add'    x      y   =  x + y
Run Code Online (Sandbox Code Playgroud)

这个方案允许你将现在的curried函数置于部分应用程序中,即将它应用于一些但不是所有的参数.例如,我们可以

succ :: Int -> Int
succ =  add' 1
Run Code Online (Sandbox Code Playgroud)

我们应用于add'它的第一个参数并产生一个仍然需要剩余参数的函数.

逆变换称为uncurrying,并将一个将其参数"逐个"的函数转换为一个函数,该函数将其参数"all once"作为元组.

两个变换都可以由高阶函数族捕获.也就是说,对于二进制函数来说

curry :: ((a, b) -> c) -> (a -> b -> c)
curry    f             =  \x y -> f (x, y)

uncurry :: (a -> b -> c) -> ((a, b) -> c)
uncurry    f             =  \(x, y) -> f x y
Run Code Online (Sandbox Code Playgroud)

对于三元函数有

curry3 :: ((a, b, c) -> d) -> (a -> b -> c -> d)
curry3    f                =  \x y z -> f (x, y, z)

uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
uncurry3    f                  =  \(x, y, z) -> f x y z
Run Code Online (Sandbox Code Playgroud)

等等.

现在让我们来看看你的例子:

2 * (\x y -> x * y) 2 3
Run Code Online (Sandbox Code Playgroud)

在这里,你是乘以文字2与功能的应用程序的结果(\x y -> x * y)是增加了它的两个参数xy.正如您所看到的,此函数已经"逐个"获取其参数.因此,它已经咖喱了.所以,如果他们要求写一个这个表达式的咖喱版本,那么你的教程意味着什么呢?我们可以做的是通过使乘法函数将参数"全部一次"接受来编写一个未经证实的版本:(\(x, y) -> x * y).然后我们得到

2 * (\(x, y) -> x * y) (2, 3)
Run Code Online (Sandbox Code Playgroud)

现在注意,一个可以写(\(x, y) -> x * y)uncurry (*),这将使我们

2 * uncurry (*) (2, 3)
Run Code Online (Sandbox Code Playgroud)

如果我们还要求第一个应用程序(或实际应用程序,复数;-))(*),我们屈服

uncurry (*) (2, uncurry (*) (2, 3))
Run Code Online (Sandbox Code Playgroud)

我怀疑这是否是你的教程练习背后的意图,但我希望这能为你提供一些关于currying和uncurrying的见解.