Higher-Order Functions

背景

说好的看Learn You a Haskell for Great Good,寒假敲了很多,到higher-order function卡了。光敲已经不能理解了。最近的早上有时候去的早就会看一看理解一下Haskell,把higher-order function看了小半,Lambdas以前的部分,准备写一写,也算是个记录。不得不感叹,这玩意真TM难懂。编程

introduction

首先简单的说一下Haskell的语法,只有这样我才能更好的把后面的东西写明白。swift

首先来看一个函数,lucky。app

lucky :: Int -> String
lucky 7 = "LUCKY NUMBER SEVEN!"
lucky x = "Sorry, you're out of luck, pal!"

这个其实和swift的语法很类似,以致于我以为swift这里很大程度上借鉴了haskell的语法。lucky做为一个函数,参数是一个Int类型,返回值是一个String类型。当咱们运行时,若是是7,就会显示是幸运数字,若是不是,那就显示sorry。函数式编程

higher-order function

什么是higher-order function。在haskell第五章的开始说了。函数

Haskell functions can take functions as parameters and return functions as return values. A function that does either of these things is called a higher-order function.学习

在wiki中得介绍是这样的。code

在数学和计算机科学中,高阶函数是至少知足下列一个条件的函数:
接受一个或多个函数做为输入
输出一个函数对象

能够看到这两个其实想表达的意思是同样的。那就是,函数做为参数,或者返回一个函数。blog

简单的说,在C语言中,咱们都是这么写的...void func(int, int) return void。ip

在haskell中,咱们能够这么写,func func(func, func) return func。

在函数式编程中,函数已经成为了头等公民。这就是高阶函数。到这基本上就能够理解面向对象老是说函数式把函数传来传去的梗了...

func return func

咱们一个一个来看。先看返回一个函数的状况。

multThree :: Int -> Int -> Int -> Int
multThree x y z = x * y * z

这是一个函数,参数是三个Int类型,返回这三个Int的乘积。

也能够写成这样。

multThree :: Int -> (Int -> (Int -> Int))

因此,咱们来分析书上的一个例子。

ghci> let multTwoWithNine = multThree 9
ghci> multTwoWithNine 2 3
54

在这里,咱们让multTwoWithNine等于了一个函数,这个函数是multThree 9。那这个时候multThree 9实际上算是返回了一个函数。那么这样的话,能够将这个函数赋值为一个变量。

也就是咱们的multTwoWithNine。这个时候咱们的multTwoWithNine实际上要计算的就是两个数的乘积再乘上9,而乘9,实际上不算是一个函数。

这里就达到了函数返回一个函数。即个人标题,func return func。

func as parameters

来看例子。

In Haskell, functions can take other functions as parameters, and as you’ve seen, they can also return functions as return values.

也就是说,函数能够将函数做为参数。

applyTwice :: (a -> a) -> a -> a
 applyTwice f x = f (f x)

这个例子种,f实际上就是一个方法。

看个例子就明白了。

ghci> applyTwice (+3) 10
16

在这里,咱们看上去applyTwice有三个参数,可是前两个参数被包起来了。也就是说,咱们有一个函数参数,一个参数和一个返回值。

f x = f (f x)实际上就是f方法执行了两次。

怎么去理解高阶函数呢?实际上在我看来,能够这么理解,第一个函数参数,实际上实现了在第三个参数的操做。

为何这里会等于16,实际上这样操做的。10 + 3 + 3。也就是,实际上第三个参数执行了函数参数的方法,获得了返回值。

说了这么多仍是混乱是吧...感受上这个例子可能不能很好的说明。那咱们看两个好懂的。

zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys

按照我上面说的,第一个函数参数,其实是a,b参数返回c。

那么咱们对[a]中的元素和[b]中的元素执行第一个函数的方法,最后返回的应该是列表中的每个元素操做后的结果。

ghci> zipWith' (+) [4,2,5,6] [2,6,2,3]
[6,8,7,9]

这个例子中,对[a]和[b]中的每个元素进行+操做。实际上就是第一个(a -> b -> c)中的操做了。

第二行和第三行的意思实际上是,第一个函数参数无论它什么类型,咱们迪哥参数和第三个参数只要是列表,就返回列表。

这么一看,其实高阶函数也不是很难吧。

再看一个map,这个在rac和rx都有用到。

map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs

咱们看这个函数,按照对zipWith'的理解,咱们知道,这个操做实际上是对[a]列表中的元素进行操做,而后这些值返回一个[b]列表。

咱们来分析一个复杂点的map。

ghci> map (map (^2)) [[1,2],[3,4,5,6],[7,8]]

首先咱们(a -> b)要进行的函数操做实际上是(map (^2)),那对第一个列表[1,2]来讲,又是一个列表了,因此要返回一个列表。(map (^2)) 1 的结果是1,(map (^2)) 2的结果是4,而后返回一个列表,即[1,4]。一次类推,因此结果就是。

[[1,4],[9,16,25,36],[49,64]]

swift中的应用

Swift 烧脑体操(三) - 高阶函数看到了swift中高阶函数的运用。

那咱们来迁移一下理解。

let arr = [1, 2, 4]
// arr = [1, 2, 4]

let brr = arr.map {
    "No." + String($0)
}
// brr = ["No.1", "No.2", "No.4"]

第一个arr.map,在map中,实际上就是实现了咱们上文map中f的应用,对列表里的每一个元素就会进行操做。实际上和haskell中的map函数没有什么差异了。

实际上来讲,高阶函数的应用不少,后面我在学习swift以后会继续说说这个高阶函数,固然,在我能搞定的状况下,我想尝试去学学Monad。

相关文章
相关标签/搜索