精华内容
下载资源
问答
  • haskell趣学指南

    2014-05-28 16:41:07
    haskell趣学指南
  • Haskell趣学指南

    2017-10-19 18:23:52
    Haskell趣学指南 字数字数字数字数字数字数字数字数字数
  • Haskell趣学指南(台译版)Haskell趣学指南(台译版)Haskell趣学指南(台译版)
  • Haskell趣学指南 pdf版

    2018-03-06 12:39:55
    此文档为Haskell趣学指南 简体中文版,希望可以帮助大家入门一用
  • Haskell趣学指南》笔记之基本语法 《Haskell趣学指南》笔记之类型(type) 《Haskell趣学指南》笔记之函数 《Haskell趣学指南》笔记之高阶函数 《Haskell趣学指南》笔记之模块 《Haskell趣学指南》笔记之自定义...

    系列文章


    目前我们提到的所有函数、type 和 typeclass 都是 Prelude 模块的一部分,默认情况下,Prelude 模块会被自动导入。

    导入模块

    import ModuleName-- 导入模块的语句必须防止在函数定义之前
    import Data.List (nubsort) -- 只导入两个函数
    import Data.List hiding (nub) -- 不导入 nub
    import qualified Data.Map -- 只能使用 Data.map.xxx 来使用函数
    import qualified Data.Map as M -- 只能使用 M.xxx 来使用函数
    复制代码

    导入之后,该模块的所有函数就都进入了『全局』命名空间。

    要查看函数位于哪个模块,可以用 Hoogle (www.haskell.org/hoogle/)。

    在 GHCi 中导入模块的语句是:

    ghci> :m + Data.List Data.Map Date.Set
    复制代码

    细节:点号既可以用于命名空间,又可以用于组合。怎么区分呢?当点号位于限定导入的模块名与函数中间且没有空格时,会被视作函数引用; 否则会被视作函数组合。

    Data.List 模块

    • words -- 取出字符串里面的单词,组成字符串列表
    • group / sort / tails / isPrefixOf / any / isInfixOf 是否含于
    • foldl' 不延迟的 foldl
    • find / lookup

    例子:

    import Data.List 
    wordNums :: String -> [(String, Int)] 
    wordNums = map (\ws -> (head ws, length ws)) . group . sort . words
    复制代码

    Data.Char 模块

    • ord 'a' -- 97
    • chr 97 -- 'a'

    Maybe 类型

    findKey :: (Eq k) => k -> [(k, v)] -> Maybe v 
    findKey key [] = Nothing 
    findKey key ((k, v): xs)    
        | key == x = Just v    
        | otherwise = findKey key xs 
    复制代码

    注意 Maybe / Nothing / Just 这三个东西。

    Data.Map 模块

    • API: fromList / insert / size / fromListWith

    使用示例

    import qualified Data. Map as Map 
    phoneBook :: Map. Map String String 
    phoneBook = Map. fromList $    
    [(" betty", "555- 2938")    
    ,(" bonnie", "452- 2928")    
    ,(" patsy", "493- 2928")    
    ,(" lucille", "205- 2928")    
    ,(" wendy", "939- 8282")    
    ,(" penny", "853- 2492")]
    
    ghci> :t Map. lookup
    Map. lookup :: (Ord k) => k -> Map. Map k a -> Maybe a 
    ghci> Map. lookup "betty" phoneBook 
    Just "555- 2938" 
    ghci> Map. lookup "wendy" phoneBook 
    Just "939- 8282" 
    ghci> Map. lookup "grace" phoneBook 
    Nothing
    复制代码

    自定义模块

    普通模块

    1. 新建 Geometry.hs

    2. 写文件

       module Geometry ( 
       sphereVolume , 
       sphereArea 
       ) where 
      
       sphereVolume :: Float -> Float 
       sphereVolume radius = (4.0 / 3.0) * pi * (radius ^ 3) 
       sphereArea :: Float -> Float 
       sphereArea radius = 4 * pi * (radius ^ 2)
      复制代码
    3. 在同一目录的其他文件里引入模块 import Geometry

    有层次的模块

    1. 新建 Geometry 目录

    2. 在 Geometry 目录里面新建 Sphere.hs / Cuboid.hs / Cube.hs

    3. 这三个文件的内容类似这样

       module Geometry.Sphere ( 
       volume , 
       area 
       ) 
       where 
       
       volume :: Float -> Float 
       volume radius = (4.0 / 3.0) * pi * (radius ^ 3) 
       area :: Float -> Float 
       area radius = 4 * pi * (radius ^ 2)
      复制代码
    4. 在 Geometry 目录的同级文件中导入模块 import Geometry.Sphere

    转载于:https://juejin.im/post/5ccd9f4151882541ea3d21b8

    展开全文
  • B10-Haskell趣学指南.pdf

    2015-09-10 21:41:01
    Haskell趣学指南.pdf Haskell 趣学指南 M. Lipovaca (英) MnO2 (繁) 开源书屋(简) 2015 年09 月10 日
  • Haskell趣学指南》笔记之基本语法 《Haskell趣学指南》笔记之类型(type) 《Haskell趣学指南》笔记之函数 《Haskell趣学指南》笔记之高阶函数 《Haskell趣学指南》笔记之模块 《Haskell趣学指南》笔记之自定义...

    系列文章


    模式匹配

    写好模式,Haskell 会直接帮你匹配。如:

    lucky :: Int -> String
    lucky 7 = "7 is the lucky number!"
    lucky x = "sorry, you are not lucky"
    复制代码

    载入之后运行

    λ> lucky 2
    "sorry, you are not lucky"
    λ> lucky 3
    "sorry, you are not lucky"
    λ> lucky 7
    "7 is the lucky number!"
    
    复制代码

    但是注意,如果把 lucky x 挪到 lucky 7 前面,就永远匹配不到 lucky 7 了。

    • 用模式匹配实现阶乘:
    factorial :: Int -> Int 
    factorial 0 = 1 
    factorial n = n * factorial (n - 1)
    复制代码
    • 定义模式的时候,一定在最后留一个万能模式,否则可能会出错
    • 元组的模式匹配
    addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double) 
    addVectors a b = (fst a + fst b, snd a + snd b)
    -- 可以改写为
    addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double) 
    addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
    复制代码
    • 模式中可以用 _ 来占位,这个 _ 叫做泛变量
    • 可以用 x: _ 来匹配列表的第一个元素 x,但是要记得加圆括号,不然 Haskell 无法理解它
    head' :: [a] -> a 
    head' [] = error "Can' t call head on an empty list, dummy!" -- error 会中断程序
    head' (x:_) = x -- 这里的圆括号不是 tuple 的标记
    复制代码
    • 匹配只有一个元素的列表,可以用 [x],也可以用 (x:[])
    • 匹配只有两个元素的列表,可以用 [x,y],也可以用 (x:y:[])
    • 匹配大于两个元素的列表,用 (x:y:_),不能用 [] 的形式
    • as 模式:all@(x:items) 中的 all 表示整个 x:items 列表,方便后面引用

    守卫/哨卫 guard

    bmiTell :: Double -> String 
    bmiTell weight height    
        | weight / height ^ 2 <= 18.5 = putStrLn "你体重不足,就像根竹竿!"
        | weight / height ^ 2 <= 25.0 = putStrLn "你体重正常,那你肯定是个丑逼!" &emsp; &emsp;
        | weight / height ^ 2 <= 30.0 = putStrLn "你体重超过,快减肥吧肥宅!" &emsp; &emsp;
        | otherwise &emsp;                      = putStrLn "你是猪!"
    复制代码

    其中的 bmi < 18.5 就是一个 guard。 每条 guard 语句至少缩进一个空格。 如果当前模式的守卫都没有 True,而且也没有写 otherwise,就会进入下一个模式。

    where

    可以使用 where 来对计算结果进行缓存,也可以定义其他的帮助函数:

    bmiTell :: Double -> String 
    bmiTell weight height &emsp; &emsp;
        | bmi <= 18.5 = putStrLn "你体重不足,就像根竹竿!"
        | bmi <= 25.0 = putStrLn "你体重正常,那你肯定是个丑逼!" &emsp; &emsp;
        | bmi <= 30.0 = putStrLn "你体重超过,快减肥吧肥宅!" &emsp; &emsp;
        | otherwise     = putStrLn "你是猪!"
        where bmi = weight / height ^ 2
                 x = "whatever"
                 getBmi weight height = weight / height ^ 2
    复制代码

    where 只在当前模式中有效。

    就算没有 guard,也可以在函数定义中使用 where:

    calcBmis :: [(Double, Double)] -> [Double] 
    calcBmis xs = [bmi w h | (w, h)< - xs] &emsp; &emsp; 
        where bmi weight height = weight / height ^ 2
    复制代码

    what 还能这样用

    describeList :: [a] -> String
    describeList ls = "The list is " ++ what ls
        where what [] = "empty."
                 what [x] = "a singleton list."
                 what xs = "a longer list."
    复制代码

    其中 what ls 是以 ls 为参数调用 what 函数。

    let

    ghci> 4 * (let a = 9 in a + 1) + 2 
    42
    复制代码

    let 和 where 相似,不同点在于 where 只允许我们在函数底部绑定变量,且对当前模式可见。而 let 可以出现在任何地方,且 let 里面的变量只在 in 内有效。

    另一个区别就是 let 是表达式(有值),而 where 不是。

    case

    case <exp> of pattern1 -> result1
                        pattern2 -> result2
                        pattern3 -> result3
    复制代码

    模式匹配不过是 case 的语法糖,而且模式匹配只能用在函数定义里,而 case 可以用在任何地方。

    转载于:https://juejin.im/post/5ccd9ec9f265da03705fc78a

    展开全文
  • Haskell趣学指南.pdf

    2017-09-24 13:12:27
    Haskell趣学指南 》这份教学主要针对已经有使用命令式程序语言 (imperative programming languages) 写程序经验 (C, C++, Java, Python …) 、却未曾接触过函 数式程序语言 (functional programming languages) ...
  • Haskell趣学指南》笔记之基本语法 《Haskell趣学指南》笔记之类型(type) 《Haskell趣学指南》笔记之函数 《Haskell趣学指南》笔记之高阶函数 《Haskell趣学指南》笔记之模块 《Haskell趣学指南》笔记之自定义...

    系列文章


    前言

    • Haskell 是纯函数式的(不能赋值,引用透明)
    • Haskell 是 lazy 的
    • Haskell 是静态类型的
    • Haskell 支持类型推导
    • :l myfunctions 可以加载同目录的 myfunctions.hs,且可以重复执行
    • :set prompt "ghci> " 可以改 prompt
      • :set prompt "λ " 可以得到 λ
      • 把这句话写在 ~/.ghci 里试试
    • putStrLn 可以打印出中文字符串

    第 1 章

    • 5 * -3 要写成 5 * (-3),不然报错
    • 布尔用 True 和 False
    • 1 + '1' 会报错,5 + 0.4 不报错,因为 5 也可以被看作 5.0

    函数

    • Haskell 中有一些中缀函数,如 * 和 +
      • 只要以特殊字符命名函数,即可自动将它视为中缀函数。
    • Haskell 大部分属于前缀函数,如
      • succ 8 是取后继
      • min 1 2 是取最小
      • max 1 2 是取最大
      • div 9 3 是除法
    • 函数调用的优先级最高,succ 9 * 10 等价与 (succ 9) * 10
    • 后缀可以变中缀:div 9 3 可以改成 9 `div` 3
    • 单参数函数 doubleMe x = x + x
    • 双参数函数 doubleUs x y = x * 2 + y * 2
    • 函数定义没有先后顺序的概念
    • 条件语句 if <condition> then <exp> else <exp> 不能省略 else
    • 条件语句是表达式而不是语句,总是有返回值
    • 函数名可以包含 ' 字符,一般以 ' 结尾的函数是非惰性求值版本,也叫严格求值
    • 函数名不能以大写字母开头,因为大写字母开头的是类型
    • 没有参数的函数被称为定义或者名字,如 a = 1

    列表

    • 列表是单类型 homogeneous 的数据结构,只能存储类型相同的元素,不能储存类型不同的元素
    • a = [1,2,3]
    • 使用 ++ 可以拼接两个列表,但是它会遍历第一个列表
    • "hello"['h','e','l','l','o'] 的语法糖
    • 使用 Cons 运算符 : 可以在列表头部插入一个元素 1:[2,3]
    • [1,2]1:2:[] 的语法糖
    • 按索引获取值可以用 !! 符号:[1,2,3] !! 0 值为 1,索引越界会报错
    • [3, 2, 1] > [2, 1, 0] 值为 True
    • 更多列表操作:head/tail/last/init/length/null/reverse/task 3/drop 3/maximum/minimum/sum/product求积
    • head [] 报错
    • 4 `elem` [3,4,5] 值为 True
    • [1..20] 生成 1 到 20 这 20 个数字组成的列表
    • ['a'..'z'] / ['K'..'Z']
    • [2,4..20] 生成 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
    • [20..1] 会得到空列表,应该写成 [20,19..1]
    • take 24 [13, 26..]
    • cycle [1, 2, 3] 会对列表进行无限循环,得到 1,2,3,1,2,3,1,2,3... 组成的列表
    • repeat 5 会得到由 5 组成的无限列表
    • repeat 3 10 会得到 [10,10,10]

    列表推导式

    • [x* 2 | x <- [1.. 10]] 得到 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
    • [x* 2 | x <- [1.. 10], x>5, filter2, filter3] 可以对 x 进行过滤
    • [ x* y | x <-[1, 3, 5], y <- [2, 4, 6]] 得到长度为 9 的列表 [2,4,6,6,12,18,10,20,30]
    • [ x* y | x <-[1, 3, 5], y <- [2, 4, 6], x* y > 10] 得到 [12,18,20,30]
    • length' xs = sum [1 | _ <- xs] 可以使用这个 length' 函数求列表的长度
    • 还能嵌套:
      ghci> xxs = [[1, 3, 5, 2, 3, 1, 2, 4, 5],[ 1, 2, 3, 4, 5, 6, 7, 8, 9],[ 1, 2, 4, 2, 1, 6, 3, 1, 3, 2, 3, 6]]
      ghci> [ [ x | x <- xs, even x ] | xs <- xxs]
      [[2, 2, 4],[ 2, 4, 6, 8],[ 2, 4, 2, 6, 2, 6]]
      复制代码

    元组 tuple

    • tuple 可以容纳不同类型的值,也就是说它是异构的
    • tuple 的长度是固定的,不能改变
    • (1,3) 是 tuple,(1,'a', "hello") 也是 tuple
    • 长度为 2 的元组也叫序对 pair
    • 二元组和三元组的类型被视为不同,所以 [(1,2), (3,4,5)] 会报错,因为列表只能包含相同类型的东西
    • 长度相同,但是里面元素的类型如果不同,两个 tuple 的类型也会被视为不同
    • 不允许长度为 1 的元组,因为这没有意思
    • 序对相关 API
      • fst (8,11) => 8
      • snd (8,11) => 11
      • zip [1,2,3] [4,5,6] => [(1,4),(2,5),(3,6)]
        • 如果 zip 的两个参数的长度不同,那么就会舍弃多余的项

    转载于:https://juejin.im/post/5ccd9e48f265da039b087f24

    展开全文
  • Haskell趣学指南》笔记之基本语法 《Haskell趣学指南》笔记之类型(type) 《Haskell趣学指南》笔记之函数 《Haskell趣学指南》笔记之高阶函数 《Haskell趣学指南》笔记之模块 《Haskell趣学指南》笔记之自定义...

    系列文章


    自定义数据类型

    一、用 data 关键字

    data 类型名 = 值构造器 | 值构造器
    data Bool = False | True
    data Shape = Circle Float Float Float | Rectangle Float Float Float Float
    复制代码

    值构造器可以直接是一个值,如 True / False 值构造器也可以是一个名字后面加一些类型

    值构造器本质上是一个返回某数据类型值的函数,所以 Circle 和 Rectangle 不是类型,是函数:

    ghci> :t Circle 
    Circle :: Float -> Float -> Float -> Shape 
    ghci> :t Rectangle 
    Rectangle :: Float -> Float -> Float -> Float -> Shape
    复制代码

    然后就可以使用这个类型了

    area :: Shape -> Float 
    -- 注意下面的模式匹配
    area (Circle _ _ r) = pi * r ^ 2 
    area (Rectangle x1 y1 x2 y2) = (abs $ x2 - x1) * (abs $ y2 - y1)
    -- 注意下面的 Circle 和 Reactangle 的位置
    ghci> area $ Circle 10 20 10 
    314.15927 
    ghci> area $ Rectangle 0 0 100 100 
    10000. 0
    复制代码

    但是现在如果你在 ghci 里输入 Circle 1 1 5 会报错,因为 Shape 不是 Show 类型类的实例,不能被 show 函数调用。 解决办法是在 data Shape 那句话的后面加一句 deriving (Show)

    data Shape = Circle Float Float Float | Rectangle Float Float Float Float &emsp;
        deriving (Show)
    复制代码

    改进

    Circle 函数接受三个 Float 参数,这三个参数前面两个是圆心的坐标,最后一个是半径。

    我们用 Point 类型来优化 Shape,使得它更已读:

    data Point = Point Float Float deriving (Show) 
    -- 注意左边的 Point 是类型名,右边的 Point 是值构造器名(类似与构造函数么?)
    data Shape = Circle Point Float | Rectangle Point Point deriving (Show)
    
    area :: Shape -> Float 
    area (Circle _ r) = pi * r ^ 2 
    -- 注意下面的模式匹配
    area (Rectangle (Point x1 y1) (Point x2 y2)) = (abs $ x2 - x1) * (abs $ y2 - y1)
    
    ghci> area (Rectangle (Point 0 0) (Point 100 100)) 
    10000. 0 
    ghci> area (Circle (Point 0 0) 24) 
    1809. 5574
    复制代码

    导出

    module Shapes ( 
        Point(..) , -- 看这里
        Shape(..) , -- 看这里
        area , 
    ) where
    复制代码

    其中 Shape(..) 的意思是导出 Shape 以及 Shape 所有的值构造器,也可以写成 Shape(Circle, Rectangle)。 当然也可以不写括号这一部分,这样别人就不能使用 Circle 和 Rectangle 函数了。

    二、用 data + 记录语法 record syntax

    data Person = Person {
        firstName::String,
        age::Int,
        height::Float,
        phoneNumber::String,
        flavor::String
    } deriving (Show)
    复制代码

    这种语法会自动创建 firstName 等函数、允许按字段取值。

    ghci> :t firstName 
    firstName :: Person -> String
    复制代码

    类型参数(很像泛型)

    data Maybe a = Nothing | Just a
    复制代码

    Maybe 是一个类型构造器(不是类型),a 是类型参数,a 可以是 Int / Char / ...,而 Just 是个函数。

    由于 Haskell 支持类型推导,所以我们只用写 Just 'a',Haskell 就知道这是一个 Maybe Char 类型。

    其实列表 [] 就是一个类型构造器,[Int] 存在,但是不存在类型 []。

    Maybe 类型的使用示例:

    ghci> Just "Haha"
    Just "Haha" 
    ghci> :t Just "Haha" 
    Just "Haha" :: Maybe [Char] 
    ghci> :t Just 84 
    Just 84 :: (Num t) => Maybe t 
    ghci> :t Nothing 
    Nothing :: Maybe a 
    ghci> Just 10 :: Maybe Double 
    Just 10. 0 
    复制代码

    data 支持类约束,但是永远不要用

    data (Ord k) => Map k v = ...
    复制代码

    书上说这只会徒增无谓的代码。

    如何让一个 type 成为类型类的实例

    只需要在 data 语句后面加上 deriving (Eq) 即可。

    在一个类型派生为Eq的实例后,就可以直接使用==或/=来判断它们的值的相等性了。 Haskell会先检查两个值的值构造器是否一致(这里只有单值构造器),再用==来检查其中的每一对字段的数据是否相等。 唯一的要求是:其中所有字段的类型都必须属于Eq类型类。

    加上 deriving (Eq, Show, Read) 就可以成为三者的实例。

    Enum 类型类

    data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
    -- 或者加上 typeclass
    data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday &emsp; &emsp; &emsp; &emsp; &emsp; 
        deriving (Eq, Ord, Show, Read, Bounded, Enum) -- 综合目前所学
        
    ghci> Wednesday
    Wednesday 
    ghci> show Wednesday
    "Wednesday" 
    ghci> read "Saturday" :: Day 
    Saturday
    ghci> Saturday == Sunday 
    False 
    ghci> Saturday == Saturday 
    True 
    ghci> Saturday > Friday 
    True 
    ghci> Monday ` compare` Wednesday 
    LT
    ghci> minBound :: Day 
    Monday 
    ghci> maxBound :: Day 
    Sunday
    复制代码

    类型别名

    type String = [Char] -- 注意不是 data 是 type
    -- 支持参数
    type IntMap v = Map Int v
    -- 等价于 point-free 风格的下面代码
    type IntMap = Map Int
    复制代码

    Either a b 类型

    data Either a b = Left a | Right b deriving (Eq, Ord, Read, Show)
    复制代码

    书上例子挺好懂,大概意思是错了就返回 Left "error message",对了就返回 Right "data message"。 不过我还不明白我怎么知道 Right "data message" 是 Right 构造出来的呢?

    递归数据结构

    data List a = Empty | Cons a (List a) 
        deriving (Show, Read, Eq, Ord)
        
    ghci> Empty 
    Empty 
    ghci> 5 ` Cons` Empty 
    Cons 5 Empty
    ghci> 4 ` Cons` (5 ` Cons` Empty) 
    Cons 4 (Cons 5 Empty) 
    ghci> 3 ` Cons` (4 ` Cons` (5 ` Cons` Empty)) 
    Cons 3 (Cons 4 (Cons 5 Empty))
    复制代码

    自制一个列表

    infixr 5 :-: 
    data List a = Empty | a :-: (List a) deriving (Show, Read, Eq, Ord)
    
    ghci> 3 :-: 4 :-: 5 :-: Empty 
    3 :-: (4 :-: (5 :-: Empty)) 
    ghci> let a = 3 :-: 4 :-: 5 :-: Empty 
    ghci> 100 :-: a 
    100 :-: (3 :-: (4 :-: (5 :-: Empty)))
    
    infixr 5 &emsp;^++ 
    (^++) :: List a -> List a -> List a 
        Empty ^++ ys = ys 
        (x :-: xs) ^++ ys = x :-: (xs ^++ ys)
    
    ghci> let a = 3 :-: 4 :-: 5 :-: Empty 
    ghci> let b = 6 :-: 7 :-: Empty 
    ghci> a ^++ b 
    3 :-: (4 :-: (5 :-: (6 :-: (7 :-: Empty))))
    复制代码

    从这个例子我大概理解黄玄说的『函数式就是 symbolism』

    这一年里一直在不断刷新自己对「FP 是什么」这个问题的回答… 之前觉得说「靠近/源自数学或者逻辑」吧,难道命令式/OO 的语言就不是描述数学和逻辑? 这种解释本身不明白这个差别的人大概听了也还是不会明白…… 今天突然觉得「(尽可能的)symbolism(符号主义)」也是个不错的描述,从 FP 语言的历史来看,主要的两个祖宗 Lisp 和 ML(LCF)都起家于符号主义 AI。 即使编程语言都是符号化的,但相比于寄托于各类外置的作用,越是「FP」越是 尽可能得希望程序的行为是可以从符号中详尽的,这因此带来了大家说的「声明式」、「可预测性」和「确定性」。

    自制一棵二叉搜索树

    data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show)
    -- 下面这个函数用来创建节点
    singleton :: a -> Tree a 
    singleton x = Node x EmptyTree EmptyTree 
    -- 下面这个函数用来插入节点
    treeInsert :: (Ord a) => a -> Tree a -> Tree a 
    treeInsert x EmptyTree = singleton x 
    treeInsert x (Node a left right) &emsp; &emsp; &emsp; 
        | x == a = Node x left right &emsp; &emsp; &emsp;
        | x < a &emsp;= Node a (treeInsert x left) right &emsp; &emsp; &emsp;
        | x > a &emsp;= Node a left (treeInsert x right)
    -- 下面这个函数用来判断元素是否在树中  
    treeElem :: (Ord a) => a -> Tree a -> Bool 
    treeElem x EmptyTree = False 
    treeElem x (Node a left right) &emsp; &emsp; &emsp;
        | x == a = True &emsp; &emsp; &emsp;
        | x < a = treeElem x left &emsp; &emsp; &emsp;
        | x > a = treeElem x right
        
    -- 使用
    
    ghci> let nums = [8, 6, 4, 1, 7, 3, 5] 
    ghci> let numsTree = foldr treeInsert EmptyTree nums 
    ghci> numsTree 
    Node 
        5
        (Node 3
            (Node 1 EmptyTree EmptyTree)
            (Node 4 EmptyTree EmptyTree)
        )
        (Node 7
            (Node 6 EmptyTree EmptyTree)
            (Node 8 EmptyTree EmptyTree)
        )
    复制代码

    转载于:https://juejin.im/post/5ccd9f72f265da03474e1282

    展开全文
  • Haskell趣学指南》笔记之基本语法 《Haskell趣学指南》笔记之类型(type) 《Haskell趣学指南》笔记之函数 《Haskell趣学指南》笔记之高阶函数 《Haskell趣学指南》笔记之模块 《Haskell趣学指南》笔记之自定义...
  • Haskell趣学指南》笔记之基本语法 《Haskell趣学指南》笔记之类型(type) 《Haskell趣学指南》笔记之函数 《Haskell趣学指南》笔记之高阶函数 《Haskell趣学指南》笔记之模块 《Haskell趣学指南》笔记之自定义...
  • Haskell趣学指南》笔记之基本语法 《Haskell趣学指南》笔记之类型(type) 《Haskell趣学指南》笔记之函数 《Haskell趣学指南》笔记之高阶函数 《Haskell趣学指南》笔记之模块 《Haskell趣学指南》笔记之自定义...
  • Haskell趣学指南 作者: [斯洛文尼亚] Miran Lipovaca 出版社: 人民邮电出版社 原作名: Learn You a Haskell for Great Good! 译者: 李亚舟 / 宋方睿 出版年: 2014-1 页数: 301 装帧: 平装 丛书: 新锐编程语言集萃 ...
  • Haskell趣学指南

    2019-07-07 02:38:17
    Haskell趣学指南》 基本信息 原书名:Learn You a Haskell for Great Good!: A Beginner's Guide 原出版社: No Starch Press 作者: (斯洛文尼亚)Miran Lipovaca 译者:李亚舟 宋方睿 丛书名:新锐编程语言...
  • Haskell趣学指南---文字版.pdf 个人收集电子书,仅用学习使用,不可用于商业用途,如有版权问题,请联系删除!
  • 为什么要学这个笔记呢? 在看这本书到functor部分之后,继续学习下去逐渐感到愈发困难,思索后觉得 学一些东西(比较新的领域,有些难度的,etc)不能追求进度和快,每一步每一步...Haskell趣学指南 英文版网站 ...
  • haskell趣学指南 高清

    2015-07-14 21:33:00
    非常好的学习资料,知乎大神推荐,对haskell学习非常有帮助,并且非常有趣
  • 本节书摘来自异步社区《Haskell趣学指南》一书中的导读,作者 【斯洛文尼亚】Miran Lipovaca,更多章节内容可以访问云栖社区“异步社区”公众号查看 目 录第 1 章 各就各位,预备! 第 1 章第 1 节调用函数第 1...
  • Haskell趣学指南1-3

    千次阅读 2010-04-27 10:21:00
    Haskell趣学指南 简介关于这个教程欢迎来到haskell趣学指南!阅读此文表明你正要学haskell。很好,来对地方了,先容我简单介绍一下这个教程。编写这个教程,一方面是为了巩固我自己对haskell的理解,另一方面也是...
  • 本节书摘来自异步社区《Haskell趣学指南》一书中的第1章,第1.1节调用函数,作者 【斯洛文尼亚】Miran Lipovaca,更多章节内容可以访问云栖社区“异步社区”公众号查看 第 1 章 各就各位,预备!Haskell趣学指南...
  • 本节书摘来自异步社区《Haskell趣学指南》一书中的第2章,第2.1节显式类型声明,作者 【斯洛文尼亚】Miran Lipovaca,更多章节内容可以访问云栖社区“异步社区”公众号查看 第 2 章 相信类型Haskell趣学指南强大的...
  • List入门-haskell趣学指南 338个读者 ssword @ yeeyan.com 12/04/2008 双语对照   原文 字体大小 小 中 大 简介 一点关于haskell中List的内容 List入门 在Haskell 中,List同现实世界中的...

空空如也

空空如也

1 2 3 4 5 6
收藏数 112
精华内容 44
关键字:

haskell趣学指南