美文网首页
📅笔记

📅笔记

作者: 梵_尘 | 来源:发表于2017-04-06 17:26 被阅读71次

    趣学指南 📅

    List:

    序列的基本操作

    let list = [1,2,3]
    head list -> [1]; head [] -> Exception
    tail list -> [2,3]; tail [] -> Exception
    init list -> [1,2]; init [] -> Exception
    take 1 list -> [1]; take 0 list -> []; take 100 list -> list
    null list -> False; null [] -> True
    reverse list -> [3,2,1]; reverse [] -> []
    drop 1 list -> [2,3]; drop 100 list -> []; drop 0 list -> list
    minimum list -> 1; minimum [] -> Exception
    maximum list -> 3; maximum [] -> Exception
    sum list -> 6; sum [] -> 0;
    sum “hello haskell” -> <interactive>:60:1: error:
    • No instance for (Num Char) arising from a use of ‘sum’
    • In the expression: sum "hello haskell"
    In an equation for ‘it’: it = sum "hello haskell"
    product list -> 6; product [] -> 1

    使用区间

    range 是构造List的方法之一,而其中的值必须是可枚举的

    Ex1: 构造1到20的自然数list

    Prelude> let o = [1..20]
    Prelude> print o
    [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
    

    Ex2: 1到20之间的偶数

    Prelude> print [2,4..20]
    [2,4,6,8,10,12,14,16,18,20]
    

    Ex3: 20到1

    Prelude> [20..1]
    []
    Prelude> [20,19..1]
    [20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1]
    

    如果不标明上限将会得到一个无限长度的序列,但由于Haskell是 惰性的 ,它不会对无限长度的list求值,它会等待你从list中取值
    不是这种惰性......

    relax.jpg

    Ex4: 取前24个13的倍数
    [13, 26..] -> 无限长度的序列
    取出前24个 take 24 [13, 26..]

    Prelude> take 24 [13,26..]
    [13,26,39,52,65,78,91,104,117,130,143,156,169,182,195,208,221,234,247,260,273,286,299,312]
    

    Ex5: cycle -> 接受一个list, 返回一个无限长度的list

    Prelude> take 10 (cycle [1])
    [1,1,1,1,1,1,1,1,1,1]
    Prelude> take 10 (cycle [1,2])
    [1,2,1,2,1,2,1,2,1,2]
    

    Ex6: repeat -> 接收一个值,返回一个该值的无限序列

    Prelude> take 10 (repeat "")
    ["","","","","","","","","",""]
    Prelude> take 5 (repeat 5)
    [5,5,5,5,5]
    

    Ex7: replicate: replicate 3 10 => [10, 10, 10]

    Prelude> replicate 3 10
    [10,10,10]
    

    List Comprehension

    序列集合 => 从序列中,通过某些条件筛选出的list
    Ex1: 简单示例,

    Prelude> [x*2 | x <- [1..10]]
    [2,4,6,8,10,12,14,16,18,20]
    

    Ex2: 添加筛选谓词

    Prelude> [x*2 | x <- [1..10], x*2 >= 12, x / 3 == 0]
    []
    Prelude> [x*2 | x <- [1..10], x*2 >= 12, x `mod` 3 == 0]
    [12,18]
    

    Ex3: 更加复杂的例子: 将输入的序列中小于10的奇数变为”BOOM!”, 大于10的奇数变为”BANG!”

    Prelude> boombangs xs = [if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x]
    Prelude> boombangs [7..17]
    ["BOOM!","BOOM!","BANG!","BANG!","BANG!","BANG!"]
    

    Ex4: 编写我们自己的length函数

    Prelude> length' xs = sum [1 | _ <- xs]
    Prelude> length' []
    0
    Prelude> length' [1]
    1
    Prelude> length' [[1], [2]]
    2
    

    Ex5: 字符串也是list,同样适用; 过滤掉字符串中除了大写字母外的其它字符

    Prelude> removeNonUppercase st = [c | c <- st, c `elem` ['A'..'Z']]
    Prelude> removeNonUppercase "Hello World!"
    "HW"
    Prelude> removeNonUppercase "sakljMjkldsjaAdljsajlCB8312789783OOK aaaaAiiiIR"
    "MACBOOKAIR"
    

    Tuple

    Tuple 简介: Tuple 和 List 很类似,都可以将多个值存入一个容器内,但是List只能存储 同种类型 的数据,而Tuple 则要求对数据的数目非常的明确。Tuple 使用()来包括内部的值。

    • Tuple 可以包含不同类型的值
    • Tuple 不可以只有一个值
    • 由于Haskell是强类型的,这样的两个tuple 无法放入 list: [(1, 2), (“g”, 10) ]将无法编译通过
    • 二元组取值 =>
    Prelude> fst (1,2)
    1
    Prelude> fst ("haskell", 9000)
    "haskell"
    Prelude> snd (1,2)
    2
    Prelude> snd ("haskell", 1888)
    1888
    

    使用zip函数来生成List

    Ex1: zip [1,2,3] [“good”, “morning”, “o”]

    Prelude> zip [1,2,3]  ["good", "morning", "o"]
    [(1,"good"),(2,"morning"),(3,"o")]
    

    Ex2: 在两个list 长度不对应时在最早结束的list处断开 => zip [1,2,3] [“l”, “p”, “ui”, “op”]

    Prelude> zip [1,2,3] ["l", "p", "ui", "op"]
    [(1,"l"),(2,"p"),(3,"ui")]
    

    Ex3: Haskell是惰性的,使用zip 函数同时处理有限和无限序列同样可以 =>
    zip [1..] [“apple”, “orange”, “mango”, “pear”]

    Prelude> zip [1..] ["apple", "orange", "mango", "pear"]
    [(1,"apple"),(2,"orange"),(3,"mango"),(4,"pear")]
    

    Ex4: 使用元组解决实际问题 =>
    取得所有三边长度皆为整数且小于等于10,周长为24的直角三角形

    Prelude> let trangles' = [(a,b,c) | c <- [1..10], a <- [1..c], b <- [1..a], a^2 + b^2 == c^2, a + b + c == 24]
    Prelude> print trangles'
    [(8,6,10)]
    

    Types and Type-classes

    Haskell 是 静态类型 语言

    => 在编译时每个表达式的类型已经完全确定。
    => 如果程序中有布尔值与整数相除的动作,将不会通过编译。

    Haskell 有类型推导

    => let a = 3, 不用告诉编译器a 是Int类型

    使用 :t 在ghci中查询数据类型

    Prelude> :t 'a'
    'a' :: Char
    Prelude> :t "hello"
    "hello" :: [Char]
    

    同样,函数也有类型,并且对于函数来说,标明类型将使代码更加清晰

    => 三个数相加:
    addThree :: Int -> Int -> Int -> Int ; addThree a b c = a + b + c

    Prelude> addTwo :: Int -> Int -> Int; addTwo a b =  a + b
    Prelude> addTwo 99 1
    100
    

    常见数据类型

    => Int : 整数,有上限和下限
    => Integer: 整数,无上下限,只和当前机器存储有关
    => Float: 单精度浮点
    => Double: 双精度浮点
    => Bool
    => Char
    => Tuple


    Type Variables 泛型

    head 函数的类型

    =>

    Prelude> :t head
    head :: [a] -> a
    

    类型名都是大写的,a并没有大写,所以a不会是一个类型。a是一个类型变数,意味着a可以是任意类别,和泛型非常类似。

    使用类别变数构造的函数称为’多态函数’,这样我们可以编写出更多与类型无关的函数

    =>

    Prelude> :t fst
    fst :: (a, b) -> a
    

    Typeclasses

    如果某一个类型属于某一种Typeclass,则这个类型必然实现了该Typeclass所描述的行为。和OC中的协议非常类似

    => ‘==‘函数的类型

    Prelude> :t (==)
    (==) :: Eq a => a -> a -> Bool
    

    Eq即为a的Typeclass, 调用该函数的类型一定是遵守了Eq所描述的行为的

    常用的Typeclasses

    => Eq: 可判断相等性的类型。除函数外的所有类型都实现了Eq,都可以比较大小
    => Ord: 包含可比较大小的类型。Ord包中包含了 > < >= <= 之类的用于比较大小的函数。compare函数比较两种相同类型的值,返回结果为GT(greater than) LT(less than) EQ(equal)

    Prelude> 5 `compare` 3
    GT 
    Prelude> "A" `compare` "Z"
    LT
    

    => Show: 包含可用字符串表示的类型。

    Prelude> show True
    "True"
    Prelude> show [1,2,3]
    "[1,2,3]"
    
    // 函数无法show
    Prelude> add8 :: Int -> Int; add8 a = a + 8 
    Prelude> show add8
    <interactive>:159:1: error:
        • No instance for (Show (Int -> Int)) arising from a use of ‘show’
            (maybe you haven't applied a function to enough arguments?)
        • In the expression: show add8
          In an equation for ‘it’: it = show add8
    

    => Read: 和Show相反,表示可以从字符串转换成某种类型的Typeclass。

    Prelude> read "[1,2,3,4]" ++ [5]
    [1,2,3,4,5]
    
    // 无法直接推断出想要转换的类型
    Prelude> read "4"
    *** Exception: Prelude.read: no parse
    
    // 可以直接指定转换的类型
    Prelude> read "4" :: Int
    4
    

    => Enum: 可枚举类型,“該 Typeclass 包含的型別有:(), Bool, Char, Ordering, Int, Integer, Float 和 Double”

    => Bounded: 有上下限的数据,使用maxBound和minBound输出上下限

    Prelude> maxBound :: Bool
    True
    Prelude> minBound :: Int
    -9223372036854775808
    

    => Num: 表示数字的Typleclass,它的成员都有数字的特征。

    Prelude> :t (*)
    (*) :: Num a => a -> a -> a
    

    => Integer: 仅仅代表整数的Typeclass,成员有Int 和Integer


    补充

    Q1: 类型是干什么用的?
    Ans: 在计算机的最底层,处理的都是没有任何附加结构的字节(Byte)。类型系统在这个基础上进行了抽象:为那些单纯的字节加上了意义,使得我们可以说“这些字节是文本”, “那些字节是机票预约数据”等等。

    Q2: Haskell 类型系统的特点
    Ans:

    1. 强类型的
    2. 静态的
    3. 自动类型推导

    相关文章

      网友评论

          本文标题:📅笔记

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