zoukankan      html  css  js  c++  java
  • 3天学习haskellhaskell第二天

    本节最重要的是map和filter他们的作用等价于list comprehension,如[x*2 | x <- [1,2..10] ]左边是map,右边是filter。

    foldl也比较重要,类似reduce函数,规约计算

    一  高阶函数

    所谓高阶函数,即输入输出均为函数的函数。

    1匿名函数(不常用,一般都用有名字的)

    语法格式为(\para1..paran->function_body)

    例如,连接字符串(\x->x++"world")"hello"

    2 map

    map可以讲一个函数映射到一个列表上

    3filter,foldl,foldr

    filter 对于列表中每个元素测试。如filter odd[1,2,3]

    fold 一个fold取一个二元函数,一个初始值(我喜欢管它叫累加值)和一个需要fold(折叠)的list。这个二元函数有两个参数,即累加值和list的首项(或尾项),返回值是新的累加值。然后,以新的累加值和新的list首项调用该函数,如是继续。到list遍历完毕时,只剩下一个累加值,也就是最终的结果

    foldl 左折叠函数 参考自 http://www.yeeyan.org/articles/view/ssword/50295

    首先看下foldl函数,也叫做左折叠。它从list的左端开始折叠,用初始值和list的头部调用这二元函数,得一新的累加值,并用新的累加值与list的下一个元素调用二元函数。如是继续。

     我们再实现下sum,这次用fold替代那复杂的递归:

     sum' :: (Num a) => [a] -> a  

    sum' xs = foldl (acc x -> acc + x) 0 xs  

    ghci> sum' [3,5,2,1]   

    11  

     我们深入看下fold的执行过程:acc x-> acc + x 是个二元函数,0是初始值,xs是待折叠的list。一开始,累加值为0,当前项为3,调用二元函数0+3得3,作新的累加值。接着来,累加值为3,当前项为5,得新累加值8。再往后,累加值为8,当前项为2,得新累加值10。最后累加值为10,当前项为1,得11。恭喜,你完成了一次折叠(fold)!

    foldr右折叠函数 (从右边开始)

    二 偏应用函数和柯里化

    一言以蔽之:每个haskell函数只有一个参数。代码中的多参数函数实际上使用柯里化机制自动变成单参数函数。(programmer dont care)

    三 惰性求值

    惰性求值是为了构建无穷列表。使用head(得到第一个),drop(去掉前几项),take(得到前几项)

    例如 myrange start step=start:(myrange start+step step)

    take 10 (myrange 10 1)

     

    四  附:列表和元组的操作函数

    参考自:http://wizardmin.com/2011/05/haskell_basic_1/

     (0) map,filter,flodr,foldl参考上边

    (1)连接 ++ :

    ++

    ghci> [1,2,3] ++ [6,7,8]   

    [1,2,3,6,7,8]

    : 

    5:[1,2,3,4]
    [5,1,2,3,4]

    (2)!! 访问列表元素
    ghci> [1,2,3,4,5,6,7] !! 1
    2

    (3)多维
    ghci> let b = [[1,2,3,4],[5,3,3,3],[1,2,3]]
    ghci> [6,6,6] : b
    [[6,6,6],[1,2,3,4],[5,3,3,3],[1,2,3]]
    但不能这样定义:b =[1,2,[3,4]],类型不一样

    (4)列表对比关系
    采用<, >,==等根据字典序进行比较
    ghci > [3,2,1] > [2,1,0]
    True

    (5)其他操作
    head 获取列表第一个元素
    ghci> head [[1,2,3],[4,5,5],[2,3,5]]
    [1,2,3]

    tail 取列表中除了第一个元素的其他元素
    ghci> tail [1,2,3,4,5]
    [2,3,4,5]

    last 取列表最后一个元素(与head对应)
    init 取列表中除了最后一个元素的其他元素(与tail对应)

    length 列表长度(不递归计算)

        ghci> length [[1,2,3], [2,1,3], [1,3,5]]   3

    null 检测列表是否为空
    reverse 反转列表

    take 从列表头开始取指定个数的元素

    ghci> take 3 [5,4,3,2,1]
    [5,4,3]
    ghci> take 8 [5,4,3,2,1]
    [5,4,3,2,1]
    ghci> take 0 [5,4,3,2,1]
    []

    drop 跳过列表头指定个数的元素的列表
    ghci> drop 3 [5,4,3,2,1]
    [2,1]

    maximum 取列表最大的元素
    minimum 娶列表最小的元素
    sum 列表总和
    product 列表乘积
    elem 判断元素是否属于列表(一般当作中缀型使用)
    ghci> 3 `elem` [3,4,5,6]
    True

    zipwtith 对两个列表的对应位置元素进行操作

    例如  zipWith (+) [1,2,3] [1,2,3]
    [2,4,6]

    (6)枚举
    在Haskell,由1到10的数字组合的列表不需列出所有数字
    ghci> [1..10]
    [1,2,3,4,5,6,7,8,9,10]

    (7)集合
    类似高等数据的集合
    例如:数学定义{2 · x| x ∈ N, x ≤ 10}
    ghci> [x * 2 | x <- [1..10]]
    [2,4,6,8,10,12,14,16,18,20]

    竖线(|)前是集合输出,竖线后是元素的定义
    ghci> [x | x <- [50..100], x `mod` 7 == 0]
    [56,63,70,77,84,91,98]

     


    元组
    元组是把不同类型的元素存储到一个值的方式,不同长度(元素个数不一样)的元组是定义为不同类型的,相同长度但对应的元素类型不一样的元素也是定义为
    不同类型。例如:[(1,2),(8,11,5)]或[(1,2),(1,'a')]是错误的。

    对(长度为2的元组)
    长度为2的元组比较常用,可以由fst和snd函数操作(不能操作长度不为2的元组)
    ghci> fst (8, 11)
    8
    ghci> snd (8, 11)
    11
    zip函数将两个列表组合成对,变成元组的列表
    ghci> zip [1,2,3,4] [5,5,5]
    [(1,5),(2,5),(3,5)](多余的元素会被删掉)


    本文参考自 《七周七语言》。


    课后题答案:

    --8.3.6
    qsort []=[]
    qsort (h:t)=(qsort(filter (<h) t) )++(num (h:t)) ++(qsort(filter (>h) t))
    num (h:t)=filter (==h) (h:t)


    qsort2 compare1 []=[]
    qsort2 compare1 (h:t)=(qsort2 compare1 (filter (compare1 h) t))++(num (h:t))++(qsort2  compare1 (filter (\x->(x/=h)&&(not(compare1 h x))) t ))


    compare1 a b=a<b


    --4
    --belazy1 x=[x]++(belazy1 x+2)
    belazy1 x=x:(belazy1 (x+2))
    belazy2 y=y:(belazy2 (y+4))


    belazy x y=(zipWith (+) (belazy1 x) (belazy2 y))
    --5
    cfun x=x/2


    --6
    func6 0 y=y
    func6 x 0=x
    func6 x y=if (x>y) then (func6 y (mod x y)) else  (func6 x (mod y x)) 


    --7sushu
    func7 =[x|x<-[1..],func77 x]
    func77 x=func777 x (x-1)
    func777 1 0=False
    func777 1 1=False 
    func777 x 1=True
    func777 x y=if( (mod x y) ==0 )then False else (func777 x (y-1))

     



     

     

     


  • 相关阅读:
    【Codechef】Chef and Bike(二维多项式插值)
    USACO 完结的一些感想
    USACO 6.5 Checker Challenge
    USACO 6.5 The Clocks
    USACO 6.5 Betsy's Tour (插头dp)
    USACO 6.5 Closed Fences
    USACO 6.4 Electric Fences
    USACO 6.5 All Latin Squares
    USACO 6.4 The Primes
    USACO 6.4 Wisconsin Squares
  • 原文地址:https://www.cnblogs.com/catkins/p/5270685.html
Copyright © 2011-2022 走看看