美文网首页
Haskell笔记2

Haskell笔记2

作者: b7c9833ccf70 | 来源:发表于2018-06-12 16:41 被阅读0次

    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]

    相关文章

      网友评论

          本文标题:Haskell笔记2

          本文链接:https://www.haomeiwen.com/subject/etzleftx.html