1 Polymorphic Types
在很多情况下,不同的数据类型会有相同功能的函数,例如判定相等或者不等,List的append等等。如果我们对每一个都单独定义的话,会产生非常多的功能一致但只有类型不同的函数。在这种情况下,polymorphic type就显得十分有用。
例如 reverse 函数, 他将一个list颠倒过来。 我们希望它对各种类型都适用那么就可定义:
reverse::[a] ->[a]
注意此处 a 即任意一种类型,[a]是显式的指明它为一个List型的类型。但是a也可以为List,[a]可以为以一种类型的list的list。
再比如说zip,
zip::[a]->[b]->[(a,b)]
此处a,b可以为一种类型,也可以为不同类型。
2 Higher-order functions
先简单介绍一下普通的function。
最基本的函数其类型是:
T->R
T,R指任意类型,T为函数的参数,R为函数的输出值。
在函数定义时,例如higher-order function, 我们可以不必再原始定义中给出参数,而是在第一次需要参数时给出定义。例如我们有函数
f::(a->a)->(a->b)->a->b
f func1 func2 = func3
where func3 input = if func1 input then func2 input
else input
在函数定义的最初,我们并没有定义 input(函数参数),但是这并不影响函数定义的合法性。 我们在func3中调用了它。这么做可以提高程序可读性。
另外,如果在函数中应用了lambda expression, 我们也可以在函数中省略参数,这只是一个参数声明的平移,因为我们还会在第一次用到参数时定义它。例如:
f::Int->Int
f = (\x->x+x)
虽然我们没有以正常的f x =..来定义函数,但是在anonymous function中我们还是给出了定义。
Haskell中,所有的函数都接收一个参数,返回一个值。那么如何解释之前写过的接收多个参数的函数?
----它们被称之为Curried functions(哎,我也不知道为什么Haskell有这么多和食物有关的术语,可能大佬是个吃货吧)。
举一个简单的例子---
引用Learn You a Haskell for Great Good!
http://learnyouahaskell.com/higher-order-functions
max:: Int->Int->Int
我们不管这个函数如何实现,总之它会选出两个数之中较大的一个。
这个函数接收第一个参数后,会返回一个接收Int的函数,最终返回a。
另一种写法为 a->(a->a), 看,它返回的是一个函数!
如果我们定义一个函数是 f = max 3,我们再调用f的时候,实际上是把缺少的一个参数补给了max。
这种应用函数的方法为 --- partial application。
回到Higher order functions来,对应只接受一个参数的函数它是first order,剩余的即higher order。higher order中会以函数作为参数,在函数定义中以括号标识出来,例如:
f:: (a->a)->b->(a,b)
(a->a)即以个以a为参数返回a的函数。
3 Lambda-abstractions
Lambda abstractions实际上是为了创造anonymous function,可以在定义函数之间方便的构造一个新的辅助函数。它的大概形式如下:
(\x -> x + x) x; (\x y -> x+y) x y
括号中为函数的定义,括号外紧跟的为函数的输入,它会替代所有x(在\x->中),或者二元的话就将对应替代---第一个数对应第一个参数,第二个对应第二个参数。
稍微复杂点的形式可以是嵌套的
大致为: \x-> (\y..) 这实际上为f.y
一个复杂一点的例子:
map (\x -> (map (\y->(x,y)) [1..10])) [0..9]
map函数对[0..9]的每一个元素都调用了中间的函数,而中间的关于x的函数是关于另一个map的函数,这个map中又有关于y的函数。它实际上等效于list:
[(x,y)|x<-[0..9],y<-[1..10]]
值得注意的一点是,transition的关系只有在括号的嵌套之中才有,如果是括号之外的另外一个anonymous function,那么就无任何关系,例如:
((\x-> x+1) 2) + ((\x->x+2) 3)
它的输出为8.
4 Higher order function 与 list
所有的list,都可以由concat,filter,map函数构造出来。
例如:
original = [ (x,y) | x <- [1..100], y <- [1..x], x `mod` y > 0 ]
它可以被改写为:
alternative = concat (map(\x->(map (\y->(x,y)) (filter (\y-> x`mod`y>0) [1..x]))) [1..100])
需要提醒的一点是,在\x->之后的括号中都为关于x的函数,所以x可以被用于任何一个子函数中,但是filter,map为分开的两个函数,所以关于y的两个函数并无关联。
5 List Function
以list为参数的function需要注意函数的non-exhaustive即详尽性或者全面性。
使用x:xs迭代性可避免各种各样的pattern match缺失。
6 ':' operator 与 '++' operator
':' operator 与 '++' 都是返回list的operator,但是:
':' 它接受一个任意类型参数加一个此类型的list参数,具体来讲是把一个参数放到一个list的首位。即类似: 1:[2,3,4] = [1,2,3,4] 或者 [1,2]:[[3,4],[5,6]] = [[1,2],[3,4],[5,6]]
a->[a]->[a]
'++': 它接受两个list类型参数,并把第二个连入第一个的尾部。即类似:
[1,2] ++ [3,4] = [1,2,3,4]
[a]->[a]->[a]
网友评论