我试图通过编写一些使用它们的简单函数来理解Haskell中的lambda函数(即匿名函数).
在下面的示例中,我只是尝试接受3个参数,并使用匿名函数添加三个参数中的两个,然后添加第三个参数.我收到一个错误,说我必须先声明一个实例.
specialAdd x y z = (\x y -> x + y) + z
Run Code Online (Sandbox Code Playgroud)
我很感激为什么我的例子不起作用的任何解释和/或任何有助于我更好地理解lambda函数的解释.
Lui*_*las 17
specialAdd x y z = (\x y -> x + y) + z
在这个例子中,你要做的是向一个数字添加一个函数,这是不可行的.看看(\x y -> x + y) + z:它有形式a + b.为了使这样的表达式起作用,a部件和b部件必须是相同类型的数字.
Haskell是一种不同寻常的语言,所以它的错误信息很少是"你不能那样做"的形式.所以这里发生的是Haskell认为这(\x y -> x + y)是一个函数,并且因为在类似的表达式中a + b,b必须是相同的类型a,所以它得出结论,它b必须也是一个函数.Haskell还允许您定义自己的规则以添加非内置类型; 所以它不能只是给你一个错误,说"你不能添加两个函数",而是错误是"你还没有定义允许我添加两个函数的规则".
以下将做你想要的:
specialAdd x y z = ((\x y -> x + y) x y) + z
Run Code Online (Sandbox Code Playgroud)
在这里,你所申请的功能(\x y -> x + y)到参数x和y,然后加入结果z.
zur*_*rgl 10
练习匿名函数的一个好方法是使用高阶函数作为折叠或贴图.
使用map作为入口点,
地图的基本定义,
map f [] = []
map f (x:xs) = f x : f xs
Run Code Online (Sandbox Code Playgroud)
建立一个例子,
>>> let list = [0..4]
>>> let f x = x + 1
Run Code Online (Sandbox Code Playgroud)
应用我们获得的地图,
>>> map f list
[1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)
现在,我们可以省略f的声明并使用匿名函数替换它,
>>> map (\x->x+1) list
[1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)
然后我们推导出, 映射f list == map(\ x-> x + 1)列表,从而
f = \x-> x + 1 --- The same as f x = x + 1, but this is the equivalent lambda notation.
Run Code Online (Sandbox Code Playgroud)
然后从一个简单的函数开始,我们看到如何将它转换为匿名函数,然后如何将匿名函数依赖于lambda抽象.
作为练习尝试翻译fx = 2*x.
现在更复杂,一个带有两个参数的匿名函数,
再一个工作的例子,
>>> let add x y = x + y
>>> foldl' add 0 [0..4]
10
Run Code Online (Sandbox Code Playgroud)
可以使用匿名函数重写为,
>>> foldl' (\x y -> x + y) 0 [0..4]
Run Code Online (Sandbox Code Playgroud)
再次使用相等我们推导出add =\xy - > x + y
而且在hakell中所有函数都是一个参数的函数,我们可以部分应用它,我们可以重写我们以前的匿名函数,add =\x - >(\y - > x + y).
然后诀窍在哪里?因为,我只是将匿名函数的使用显示为高阶函数,并从此开始,显示如何利用lambda表示法来重写函数.我的意思是,它如何帮助您学习如何写下匿名函数?
简单地说,我已经使用高阶函数给你(给你看)一个现有的框架.
这个框架是一个巨大的机会,可以为您提供这种表示法.
从中可以推断出无限范围的运动,例如尝试执行以下操作.
A - Find the corresponding anonymous function ?
1 - let f (x,y) = x + y in map f [(0,1),(2,3),(-1,1)]
2 - let f x y = x * y in foldl' f 1 [1..5]
B - Rewrite all of them using lambda notation into a declarative form (f = \x-> (\y-> ...)
Run Code Online (Sandbox Code Playgroud)
等等 ....
总结一下,
功能如
(F0) f x1 x2 ... xn = {BODY of f}
Run Code Online (Sandbox Code Playgroud)
总是可以重写为,
(F1) f = \x1 x2 ... xn -> {BODY of f}
Run Code Online (Sandbox Code Playgroud)
哪里
(F2) (\x1 x2 ... xn -> {BODY of f})
Run Code Online (Sandbox Code Playgroud)
F2形式只是匿名函数,将函数纯粹转换为lambda演算形式.F1是一个声明性的lambda表示法(因为我们声明f,因为我们定义它,将它绑定到匿名F2).F0是Haskeller的常用符号.
最后一个注意事项,我们可以在参数之间加上括号,这就创建了一个闭包.这样做意味着可以使用函数参数的子集完全评估函数代码的子集(意味着转换为不再发生自由变量的形式),但这是另一个故事.