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))

     



     

     

     


  • 相关阅读:
    Java -- 最简单的认识重载
    maven打包spring boot项目及跳过test文件
    springboot 配置elasticsearch Java High Rest Client
    面向对象与面向过程的区别
    vue --- axios拦截器+form格式请求体
    kotlin --- 时间戳与字符串互相转换
    各种技术的路线图
    bpmn-js起步
    纵观 jBPM:从 jBPM3 到 jBPM5 以及 Activiti5
    几大工作流引擎对比
  • 原文地址:https://www.cnblogs.com/catkins/p/5270685.html
Copyright © 2011-2022 走看看