Haskell从零学习读书笔记+参考资料(续中)

思科模拟器Cisco Packet Tracer交换机的管理配置 一、交换机的管理方式:带内管理和带外管理 通过交换机的 Console 端口管理交换机属于带外管理;这种管理方式不占用交换机的网络端口,第一次配置交换机必须利用 Console 端口进行配置。 通过 Telnet、拨号等方式属于带内管理。 二、控制台配置思科交换机 1.新建拓扑图 新建拓扑,选择console线连接交换机和PC,一端接交换机的console口,一端接PC的RS 232 口(... 阅读详情


通过阅读:

https://zh.wikibooks.org/wiki/Haskell/列表和元组

https://www.kancloud.cn/kancloud/learnyouahaskell/44654 Haskell趣学指南

https://rwh.readthedocs.io/en/latest/index.html RealWorld中文版

我分别学习了wikibooks和Haskell趣学指南.
所有的代码我都做了实践.并且修复了部分原文中的BUG笔误.
本笔记可作为辅助学习用.

Haskell学习笔记 -wikibooks

注意这只是笔记,并不能完全代替原教程学习.

基本

ghci是Haskell 的交互式命令行

退出方式是:q或者:quit

变量和函数

let number= 1234 in xxx

函数声明和调用:

即let 函数名 参数列表 = 运算


let func1 firstArgv secondArgv = firstArgv+secondArgv

func1 1 2 //结果是3

列表与元组

列表

note that: List中的List可以 长度不同,但必须得是 相同类型.


[[1,2,3],[1]] //合法

定义一个列表


let numbers = [1,2,3,4];

将数据附加到列表中使用: cons操作符eg:


1234:numbers //结果是 [1234,1,2,3,4]

结果还是列表所以复合用法是:


let x = [0]

1:3:2:x //结果是 [1,3,2,x]

实际上所有的列表都是在一个空的列表[]的基础上附加数据创建的:即以下相等:


[1,2,3,4,5]

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

列表能包含列表.

元组

把多个值存储到一个值的方法.

可用于返回值,避免了某些语言 到处临时定义结构的麻烦:


(True,1)

("Hi",Flase,4,5)

n个元素叫n-tuple.

元组用于函数返回多个值.

不同类型顺序和数量的元组 视为 类型不同.


[1,"a"]

["a",1]

如何从 元组 中把数据取出?

fst 和 snd可以分别把第一个和第二个数据 取出.

通用技巧是:模式匹配函数式编程的出众特征.

fst的原理:


let first (x,y) = x

元组能嵌套

Haskell文件

Haskell源文件

:load 加载一个hs源码库文件

:reload重新加载

:cd 切换目录

源文件

没有let

源文件里 不用 let?

不能定义同一个量两次
顺序不重要

因为变量不可改变

函数的更多特性

条件表达式

if / then /elseeg:


mySignum x =

if x < 0 then

-1

else if x > 0 then

1

else

0

测试方法:

mySignum(-1)

mySignum 2

mySignum 0

case

除了在 模式匹配中 拥有强大功能外,还可以 替代 if 改善可读性.


fcase x =

case x of

0 -> 1

1 -> 5

_ -> (-1)

注意缩进非常重要.

使用一个layout的布局系统对程序的代码进行维护.

缩进

分号和花括号 的方式 可以代替以上的缩进:


f x = case x of

{0->1;1->5;_->(-1)}

为不同参数定义一个函数

分段定义方法:


f 0 = 1

f 1 = 5

f _ = -1 //注意顺序

函数合成

square (f 1)

. 函数,函数的合成函数.将两个函数合成为一个函数.

(square . f)表示一个有参数的函数,先把这个参数代入函数f,再把结果代入函数square.


fa a = a+1

fb b = b+1

bc c = c+1

(fa . fb . fc) 0 //相当于fa(fb(fc 0))

Prelude 中 定义了很多函数,所以用前可以看看不用自己实现了.

let绑定

let 语句可以同时声明多个值,只要保持相同缩进:


roots a b c =

let disc = sqrt(b^2 - 4*a*c)

twice_a = 2*a

in ((-b + disc) / twice_a,

(-b - disc) / twice_a)

局部绑定可以解决函数中重复的问题:let/in

// 这个用法需要更深入了解

快速排序


quicksort [] = []

quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)

where

lesser = filter (< p) xs

greater = filter (>= p) xs


q_sort n=case n of

[]->[]

(x:xs)->q_sort [a|a<-xs,a<=x]++[x]++q_sort [a|a<-xs,a>x]

// //(x:xs)-->把传递的数组结构分成首项+剩余两个部分 同时作为参数传递到后面的函数中,首项的作用就是上面说的a啦,当然也可以时最后一项,这里取首项时方便一些

//[a|a<-xs,a<=x] 这里是什么意思呢?a|,这个a代表输出,可以理解为返回值,a<-xs,a<=x表示这个a从xs中来,同时a小于x,也就是传进来的去掉第一项的数组,输出小于等于x的数组元素,综合来看,这句话实现了:把小的数组元素扔左边的功能;



---------------------

作者:gohike

来源:优快云

原文:https://blog.youkuaiyun.com/gohike/article/details/52719409

版权声明:本文为博主原创文章,转载请附上博文链接!

列表推导

我们可以像描述数学问题一样来描述一个列表表达式: 结果是个整数.


> [x*2| x<- [1..10]]

[2,4,6,8,10,12,14,16,18,20]

获得 100 以内 所有6的倍数, 通过列表推导 快速获得:


>[x | x <- [1..100],mode x 6 == 0]

计算直角三角形的问题:斜边的长度为 1-10 之间的整数,求可能的三角形边长。


> [(a,b,c)| a<- [1..10],b <- [1..a],c<-[1..b],b^2+c^2==a^2]

[(5,4,3),(10,8,6)]

另一个例子:


[a|b<-[1..120],a<-[b^2]]

规则推测是: [结果|条件式子一们]

<-符号来自于.

趣学入门 - 教有其他语言基础的人怎么学

https://www.kancloud.cn/kancloud/learnyouahaskell/44654 Haskell趣学指南

第二章 入门

函数 首字母不能大写,标识符可以用'号来表达,经过略微修改的函数.

没有参数的函数通常被称为定义

List入门


head [1,2,3,4]

tail //返回除头外

last //尾

init //返回除了尾外的List

length

List 有自己的一堆函数:

take x// 返回前x个元素

reverse //翻转

maximum

minimun

null //检查空

sum

product //所有元素的积

elem //判断元素是否存在其中,常以中缀方式出现

elem 4 [1,2,3,4]

的中后缀表达是: 4 `elem` [1,2,3,4]

用撇号来包含住函数.

List合并: 使用 ++运算符.注意数据太大时,因为遍历整个List,会慢,好的办法是在前面直接加数据:


5:[1,2,3,4]

字符串实际上是一组字符的list语法糖.以下等同


> ['h','i']++" how are you"

"hi how are you"

length函数:

my_length xs = sum [1| _<-xs]

区间Range

[1…3]和[1,2,3]完全等价.

[‘a’…‘z’]字母也可以提供区间

还允许你声明步长

[2,4…20] // 后面的20是结束,只会根据2,4的规律来.

[2,4…21] //结果一样.

避免在Range内使用浮点数,因为浮点数是不精确的.可能推测出0.8999999之类.

[13,26…] //可以不标明上限,获得无限长的List,按需生成,

take 10 [13,26]//从中获取10个数字

cycle可以将提供的List参数返回一个无限长的List

repeat 将一个值输入返回一个无限List

take 5 repeat 4 // [4 ,4 ,4 ,4 ,4]

或者用replicate 获取指定数量的重复:

replicate 3 4//[4,4,4]

集合 Comprehension

集合表示: S= {2*x | x<-N,x<=10}

**|**左是输出函数,x是变量,N是输入集合

再添加个限制条件:要求x*2>=12:

[x*2| x<- [1..10],x*2>=12]

一个从List中筛选的过程叫做:filtering过滤.

boomBangs xs = [if x<10 then “BOOM!” else “BANG!”| x xs, odd x]

//odd是限制是否奇数

**=**表示不等于.

另一个例子:

[x*y| x<-[1,2,3],y<-[1,2]]//最终结果会是6个.

以下是从嵌套List中找偶数,且不需要拆开嵌套的List.用法如下:


let xxs = [[1,2,3,4]]

[[x| x<-xs ,even x]| xs <- xxs]

Tuple 元组

以下函数只能用于二元组

fst (1,2)

snd (1,2)

zip [1,2] [3,4] //可用与生成一组二元List,常用在需要组合或是遍历两个List时.如下是个例子:

[(1,3),(2,4)]//一一对应做组合

函数式编程的一般思路:

先取一个初始的集合并将其变形,执行过滤条件,最终取得正确的结果。

第三章 类型和类型类

与Java相比,haskell支持类型推导.

这样我们就不必在每个函数和表达式上都表明其类型了.

:t 表达式

可以检测表达式的类型在ghci.

Char,Bool,[Char] //一组字符的List

(在文件中)声明类型是个好习惯,方法是:: 最后一个Int是返回值的类型:


addThree :: Int -> Int -> Int -> Int

addThree x y z = x + y + z

Int:整数有范围限制:

对32位的机器而言,上限一般是214748364,下限是-214748364。

Integer:是无界的.想多大就多大.但效率<Int.

Float 单精度的浮点数

Double 双精度的浮点数

类型变量

类型变量可以让我们轻而易举的写出类型无关的函数.

使用类型变量 的函数被称作"多态函数".


ghci> :t fst

fst :: (a, b) -> a // 类型必须是首字母大写,它是小写,代表它是任意类型

类型类

类型类 可以理解为接口.


ghci> :t (==)

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

其中 => 为类型约束

取两个相同类型的值作为 作为参数 并返回一个Bool,这两参数的类型同在 Eq之中 (即类型约束)

Eq这一类型类 提供了 判断 相等性的接口,反是可比较相等性的类型 必属于Eq类

另一个例子:

elem函数的类型为: (Eq a)=>a->[a]->Bool

因为它内部使用了==的缘故.

几个基本的类型类
  • Eq

可判断相等性的类型,提供实现的函数是**==** 和 /=.

除函数以外的所有类型都属于Eq类,都可以判断相等性。

  • Ord

包含可比较大小的类型,除函数以外,结果是三种类型之一: GT,LT,EQ

compare 1 2

  • Show

它的成员为可用字符串表示的类型,除函数以外,

操作Show类型类,常用函数**show **取任一Show的成员类型并将其转为字符串.


show 3 //"3"

show True //"True"

  • Read

与Show类型类相反,将一个字符串转为Read的某成员类型:

其中常用函数 read:


read "3.1" + 3.8 //6.9

read "[1,2,3,4]" ++ [3] // [1,2,3,4,3]

read必须推断出要什么类型,虽然编译器可以辨认出 大部分 表达式的 类型:


read "3" //提示错误,它不知道要转换成哪种类型

read "3"::Float //正确

  • Enum

成员必须都是连续的类型(可枚举的).

好处: 可在Range中用到它成员类型,每个值都有:前一个 successer 和 后一个 predecesor.

可用succ和pred函数得到.


succ 'B' //'C'

pred 'b' // 'a'

(),Bool,Char,Ordering,Int,Integer,Float和Double。

  • Bounded

它的成员,都有一个上限和下限.


minBound :: Char // "\Nul"

maxBound :: Bool // "True"

  • Num

包含实数和整数

  • Integral

  • Floating

fromIntegral函数 处理数字非常有用:

其类型声明为:

fromIntegral :: (Num b, Integral a) => a -> b

取一个整数做为参数,返回一个更加通用的数字.

fromIntegral (length [1,2,3,4]) + 3.2 // 直接加3.2不行…历史原因…

第四章 函数的语法

模式匹配

通过检查数据 的 特定结构 来检查其 是否匹配,并 按模式 从中取得数据.

模式匹配 使 我们避免了一颗大的 if-else树.


sayMe :: (Integral a) => a -> String

sayMe 1 = "One"

sayMe x = "No 1"

阶乘的玩法:


fac :: (Integral a) => a -> a

fac 0 = 1

fac n = n* fac(n-1)

就想 sayMe x一样.

因此,在定义模式时,一定要留一个万能匹配的模式,这样我们的程序就不会为了不可预料的输入而崩溃了。

list本身也可以使用模式匹配,你可以用 [] 或 :来匹配

因为[1,2,3]在表达1:2:3:[]的语法糖

x:xs <- [1,2,3] //这种模式 可以将 list的头部绑定为x,其他部分绑定为xs

其中x为[1],xs为[2,3].

绑定多个变量怎么处理?

x:y:z:xs此时就获取xs的前三个变量.

实现个自己的head函数:


head_ :: [a] -> a

head_ [] = error "dummy!"

head_ (x:_) = x

对于固定长度的List,eg:

(x:[ ]) 和(x:y:[ ]) 可以写为 [x]和[x,y]


length' :: (Num b) => [a] -> b

length' [] = 0

length' (_:xs) = 1 + length' xs

as模式

as模式是为了 在较大的 模式中保留对整体的引用,从而减少重复性的工作:


capital :: String -> String

capital "" = "Empty string, whoops!"

capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]

-- capital (x:xs) = "The first letter of " ++ x:xs ++ " is " ++ [x]

看上面两条是等效的.但是第1条更简约.

门卫 guard

模式用来 检查一个值是否合适并从中取值.

Guard用来检查一个值的某项 属性是否为真. 像if,但是可读性更高,与模式匹配契合的很好.

门卫由 函数名和参数后面的竖线**|**表示,每个门卫都是一个布尔表达式,真就执行相应函数体.


bmiTell bmi

| bmi<18.5 = "瘦"

| bmi<25.0 = "正常"

| bmi<30.0 = "超重"

| otherwise = "肥胖"

其中otherwise = true.

Where

where是紧跟在函数体底部定义 的用来定义 多个名字和函数 的 方法.(局部变量)

对门卫可见.


bmiTell weight height

| bmi<18.5 = "瘦"

| bmi<normal = "正常"

| bmi<30.0 = "超重"

| otherwise = "肥胖"

where bmi = weight /height ^ 2

normal = 25.0

另一个获取姓名的首字母的函数 使用where和模式匹配的例子:


initials :: String -> String -> String

initials firstname lastname = [f] ++ ". " ++ [l] ++ "."

where (f:_) = firstname

(l:_) = lastname

where 可以嵌套,一种广为接受的理念:

一个函数应该有几个辅助函数,而每个辅助函数也可以通过where拥有各自的辅助函数.

Let

  • 允许在任何位置定义 局部变量 或 局部函数

  • 对不同的门卫不可见

  • 是个表达式,比where要灵活自由

let [绑定] in [表达式],绑定的名字仅对in部分可见.


(let a = 100; b = 200; c = 300 in a*b*c, let foo="H"; bar = "i" in foo ++ bar) // (6000000,"Hi")

在let绑定的前面无法使用它.因为还没有定义…

let是个表达式,定义域限制的相当小,因此不能在多个门卫中使用.

所以我们 还需要where的.

case表达式

模式匹配 本质上 不过就是case语句的语法糖而已,以下代码完全等价:


head' :: [a] -> a

head' [] = error "No head for empty lists!"

head' (x:_) = x

--

head' :: [a] -> a

head' xs = case xs of [] -> error "No head for empty lists!"

(x:_) -> x

语法如下:


case expression of pattern -> result

pattern -> result

pattern -> result

...

另外一个例子是:


describeList :: [a] -> String

describeList xs = "The list is " ++ case xs of [] -> "empty."

[x] -> "a singleton list."

xs -> "a longer list."

也可以写成 where 语法: (其中what 是我们自己定义的函数)


dL :: [a] -> String

dL xs = "Is " ++ what xs

where what [] = "Empty"

where [x] = "Singleton list"

where xs = "a longer list"

That Tips: 错误的缩进会导致错误


qian_xin' moun =

case moun of 12 -> "1"

1 -> "2"

2 -> "2"

3 -> "3"

4 -> "4"

moun -> error "不考虑"

case of 的选项如果 ,12 ,1 ,2, 3, 4 ,moun不在同一排上就会提示以下:


Unexpected case expression in function application:

case moun of

12 -> "1"

1 -> "2"

2 -> "2"

3 -> "3"

4 -> "4"

You could write it with parentheses

Or perhaps you meant to enable BlockArguments?

|

103 | case moun of 12 -> "1"

| ^^^^^^^^^^^^^^^^^^^^^^^^...

Failed, no modules loaded.

第五章 递归

斐波那契数列:


fib 0=0

fib 1=2

fib num = fib (num-1) + (fib num-2)

边界条件对于递归至关重要.

命令式语言要求你提供 求解的步骤

Haskell 倾向于让你 提供 问题的描述

所以没有while和for循环的原因. 递归是我们的方案.

求列表最大


maximum'' [] = error "empty list!"

maximum'' [x] = x

maximum'' (x:xs)

| x > maxTail = x

| otherwise = maxTail

where maxTail = maximum'' xs





maximum' [] = error "empty list!"

maximum' [x] = x

maximum' (x:xs) = max x (maximum' xs)



先定义边界条件

最定义递归过程

几个递归函数

自己定义一个replicate

重复 time 个 num在列表中:

以下是两个例子:


replicate' time num

|time >0 = num:(replicate' (time-1) num)

|time == 0 = []

|otherwise = error ("error: <0")




replicate' :: Int->Int->[Int]

replicate' num (0) = []

replicate' num time>2 = num:(replicate' num (time-1))

自定义一个take

这里用到的技巧是分情况处理,而不局限于一个函数中:


take' :: (Num i,Ord i) => i->[a]->[a]

take' n m

| n<=0 = []

|(null m) = error "No enough!"

take' n (x:xs) = x:take'(n-1) xs

另一个版本是教程的:


take' :: (Num i,Ord i) => i->[a]->[a]

take' n _

| n <= 0 = []

take' _ [] = []

take' n (x:xs) = x : take' (n-1) xs

特点:是其未使用null来辅助判空,而是直接 模式匹配用 []来处理.

模式匹配是关键.!

自定义一个库函数 elem

该函数用来检查是否属于包含关系:

我实现的版本:


elem' :: Ord a=> a-> [a] -> Bool

elem' _ [] = False

elem' n (x:xs)

| n==x = True

| otherwise = elem' n xs

作者实现的版本更好的限制了类型:


elem' :: (Eq a) => a -> [a] -> Bool

elem' a [] = False

elem' a (x:xs)

| a == x = True

| otherwise = a `elem'` xs

简单直接. 若头部不是该元素, 就检测尾部, 若为空List就返回False.

排序-快排

我用where做:


qsort'' :: Ord a=> [a]->[a]

qsort'' []=[]

qsort'' (x:xs) =

small ++ [x] ++ big

where

small = qsort''([a|a<-xs,a<=x])

big = qsort''([a|a<-xs,a>x])

let in 来做:


qsort'' :: Ord a=> [a]->[a]

qsort'' []=[]

qsort'' (x:xs) =

let

small = qsort''([a|a<-xs,a<=x])

big = qsort''([a|a<-xs,a>x])

in

small ++ [x] ++ big



我认为其他语言用栈做这个事件似乎比较合适.

我们已经递不少归了,也许你已经发觉了其中的固定模式:先定义一个边界条件,再定义个函数,让它从一堆元素中取一个并做点事情后,把余下的元素重新交给这个函数。 这一模式对List、Tree等数据结构都是适用的。

再者就是边界条件。一般而言,边界条件就是为避免程序出错而设置的保护措施,处理List时的边界条件大部分都是空List,而处理Tree时的边界条件就是没有子元素的节点。

使用递归来解决问题时应当先考虑递归会在什么样的条件下不可用, 然后再找出它的边界条件和单位元, 考虑参数应该在何时切开(如对List使用模式匹配), 以及在何处执行递归.

第六章 高阶函数

柯里函数

好熟悉的名字,柯里化…

本质上,haskell所有函数都只有一个参数.

所有多个参数的函数都是 柯里函数


max 4 5

(max 4) 5



mulThree x y z = x*y*z

((mulThree 3) 5) 9



((mulThree 3) 5) 9或mulThree 3 5 9

背后的运行原理:

  1. 把3 交给 mulThree,它返回一个返回函数的函数.

  2. 然后把5交给它.返回一个 取一个参数并使之乘15的函数

  3. 把9交给这一函数,返回135.

想想,这个函数的类型也可以这样写:


mulThree:: (Num a) => a -> (a -> (a -> a))

->前面的东西就是函数取的参数,后面的东西就是其返回值.所以说,我们的函数取一个a,并返回一个类型为(Num a)=>a ->( a->a)的函数.如此递推.

以不全的参数调用函数可以方便创造新的函数.


compareWithHundred = compare 100

compare 100会返回一个取一数与100比较的函数.

不全调用在中缀运算中的用法:

divTen = (/10) //加括号即可

(/10) 200,和 200/10 等价.

注意,返回的函数是无法打印的,因为函数不是Show 类型的实例:

会显示 类似以下错误:


<interactive>:16:1: error:

? No instance for (Show (Integer -> Integer))

arising from a use of ‘print’

(maybe you haven't applied a function to enough arguments?)

? In a stmt of an interactive GHCi command: print it

高阶函数

函数是一等公民,所以,取一个函数做为参数和返回值.

例子是一个函数 applyTwice 接收一个函数,并调用它两次.

Note that: **->**具有右结合性,所以需要一个括号来表明这是一个函数.


applyTwice:: (a->a) -> a -> a

applyTwice f a= f(f(a))



applyTwice (3:) []

applyTwice ("Hi " ++) "L"

-- "Hi Hi L"

applyTwice (++ "Hi") "L"

-- "L Hi Hi"

以上是不全调用的展示,

我的理解: 不全调用函数可以被串连使用等,就像普通的函数.

如果有个函数要我们给它传一个一元函数,可以不全调用一个函数让它剩一个参数,再把它交出去.

这是作者认为神奇的点.

实现zipWith库函数

zipWith 有三个参数: 一个函数,两个List,结果是一个List.

用两个List中的同一个序号的项传给函数,结果得到一个项。


zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]

zipWith' _ [] _ = []

zipWith' _ _ [] = []

zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys

其中 f x y : zipWith' f xs ys的语法就是普通的 将一个元素放入列表中…

一个简单的的高阶函数可以玩出很多花样.

命令式语言使用for,while,赋值,状态检测来实现功能,再包起来留个接口,使之像个函数一样调用.

函数式语言使用高阶函数来抽象出常见的模式,像成对遍历并处理两个List或从中筛掉自己不需要的结果.

实现flip库函数

flip能实现将参数给换个个.返回结果依然是个函数


flip':: (a -> b -> c) -> (b -> a -> c)

flip' f a b = f b a

//这里体验了柯里函数的优势,只要调用flip' f,而不加参数即可获得 新函数.

实现map和filter

map用途广大.


map(map (^2)) [[1,2],[3,4]] //[[1,4],[9,16]]

map (++ "!") ["Hi","How","Ok"]

map 的功能都可以用List Comprehension来替代:

[a++"!"|a<-["Hi","How","Ok"]]

filter 是 传入一个判断函数,和一个列表,用每一项调用判断函数.

如果True就添加到返回列表中


filter' :: (a->Bool) -> [a] -> [a]



filter' _ []=[]

filter' f (x:xs)

| f x = x:filter' f xs

| otherwise = filter' f xs

filter (==3) [1,2,3,4,5,6]

同样可以用List Comprehension方法:

[a|a<-[1,2,3,4,5,6],a==3]

我发现递归似乎是一个从底向顶展开的过程.

作者建议: map, filter 或者 List Comprehension 哪个舒服用哪个.

以下是快排的filter版本:


quicksort :: (Ord a) => [a] -> [a]

quicksort [] = []

quicksort (x:xs) =

let smallerSorted = quicksort (filter (<x) xs)

biggerSorted = quicksort (filter (>x) xs)

in smallerSorted ++ [x] ++ biggerSorted



takewhile 函数 它取一个限制条件和List做参数.

返回符合限制条件的元素,一遇到不符合条件的元素,它就结束了.

求所有小于10000的奇数的平方的和:


sum (takeWhile (<10000)(filter odd (map (^2)[1..])))

在大于10000处将它断开.结果是:166650

haskell的惰性使得其可以在 延迟在任何时间进行断开.

而不是 一开始就必须设定范围.

取List第X个元素!! x:


[0,1,2]!!2 //结果是2

运用柯里函数和不全调用 函数 可以创造函数列表:

以下内容写在ghci控制台即可:


ghci> let listOfFuns = map(*)[0..]

ghci> (listOfFuns !! 4) 5

20

和4*5等价.

实现lambda

对于只用一次的函数 可以 使用labmda.

在Haskell中lambda匿名函数的表示方法是\开头的函数.

如果不希望整个行被识别为 lambda可以用括号将其括起来.eg:


numLongChains :: Int

numLongChains = length (filter (\xs = length xs > 15) (map chain [1..100]))

其中xs = length xs> 15就是lambda.

不熟悉柯里函数与不全调用的人们往往会写出很多lambda,而实际上大部分都是没必要的。例如,表达式map (+3) [1,6,3,2]与map (\x -> x+3) [1,6,3,2]等价,(+3)和(\x -> x+3)都是给一个数加上3。不用说,在这种情况下不用lambda要清爽的多。

lambda中无法为一个参数设置多个模式,如[] 和 (x:xs)同时设置

lambda的模式匹配如果失败,就会引发运行时错误,谨慎使用!

以下的等价内容将后面的整个语句做为lambda的函数体,更能说明柯里化.


addThree :: (Num a) => a -> a -> a -> a

addThree x y z = x + y + z





addThree :: (Num a) => a -> a -> a -> a

addThree = \x -> \y -> \z -> x + y + z

折叠纸鹤
有$的函数调用
函数组合

模块

构造我们自己的类型和类型类

待续

疑问

? 能否实现一个四则计算器?

?能否方便实现各种parse?

?进制转换?生存

?支持正则吗?

?调用API?

计划

做高级编译器 -> 其他源码阅读 -> 操作系统

-> TCP/IP协议详解卷一

https://www.kancloud.cn/lifei6671/tcp-ip

接下来做什么呢?

指得是当达到Haskell的目标后

网络真是吸引人的.TCP/IP协议详解卷一,将是我们的下一个目标,

理由是我们接下来的发展方向是偏网络, 而这是基础.

这将会大幅增强我们的网络技能.

同样它是其他源码阅读的基础

XXXX

|

TCP/IP

Qt | QPalette 类(调色版) 阅读详情

相关推荐

奇迹MU单机版开服全流程:从零搭建到分辨率调整(附GM工具使用技巧)

本文详细介绍了奇迹MU单机版从零搭建到分辨率调整的完整流程,包括环境配置、服务端启动、GM工具使用技巧等关键步骤。特别针对现代高分辨率显示器提供了优化方案,帮助玩家轻松搭建个性化游戏环境,重温经典MMORPG的独特魅力。

b3n4m5q6w7的博客 682

两头羊支付Api对接文档(Haskell)

Haskell(发音为/ˈhæskəl/)是一种标准化的,通用的纯函数编程语言,有非限定性语义和强静态类型。它的命名源自美国逻辑学家哈斯凯尔·加里,他在数理逻辑方面上的工作使得函数式编程语言有了广泛的基础。在Haskell中,“函数是第一类对象”。作为一门函数编程语言,主要控制结构是函数。Haskell语言是1990年在编程语言Miranda的基础上标准化的,并且以λ演算为基础发展而来。这也是为什么Haskell语言以希腊字母“λ”(Lambda)作为自己的标志。Haskell具有“证明即程序、命题为类型”

ltyzf888的博客 461

用Matlab和CVX搞定原子范数最小化:一个信号处理小白的避坑实践

本文详细介绍了如何使用Matlab和CVX实现原子范数最小化(Atomic norm minimization),特别适合信号处理初学者。从CVX安装配置、核心代码解析到实战中的典型问题与解决方案,提供了全面的避坑指南。通过具体案例展示了原子范数在频率估计和DOA估计中的优势,并给出性能优化策略和可视化方法。

weixin_28731231的博客 233

Haskell 常用方法

succ 返回后继元素 pred 返回前驱元素 div 整除商 list函数 head tail last init length null reverse take drop minimum sum product elem cycle repeat(cycle 将元素当元素重复,repeat将整个列表重复) replicate show 无条件转化为字符串 read

寒烛的博客 800

IPD(集成产品开发)管理之道

IPD,是集成产品开发(Integrated Product Development)的缩写,它是集成了众多管理模型和理论、众多企业最佳管理实践的一整套体系,可以帮助企业快速响应市场变化、缩短产品上市时间、减少资源浪费、提高生产力,最终取得商业成功。IPD的思想最早来源于美国PRTM公司出版的《产品及生命周期优化法》一书中,该书详细描述了IPD模式所包含的各个方面。但IPD在中国的普及,源于IBM和华为的推行使用。IPD作为一套先进的产品研发管理模式,其成功的基础是功能部门和各团队之间的密切配合。

钢镚·真的博客 2715

3D坐标系转换实战:如何用Python快速实现旋转矩阵与平移向量的组合变换

本文详细介绍了如何使用Python和NumPy实现3D坐标系转换中的旋转矩阵与平移向量的组合变换。通过齐次坐标和变换矩阵的数学原理,结合代码示例,帮助开发者高效处理机器人路径规划和计算机视觉中的空间变换问题,并解决实际应用中的常见错误。

pluto的博客 960

Haskell 5

定义一个自然数类型 思路: –0是自然数 –if n 是自然数,n+1是自然数 data Nat = Zero | Suc Nat deriving Show —Suc 是后继的意思nat2Int :: Nat -> Int —Nat类型转换成Int类型 nat

a853130236的博客 853

使用 Python 爬虫抓取 IMDb 电影信息 - 评分、评论与基本信息抓取教程

本文介绍了如何使用 Python 爬虫技术抓取 IMDb 电影评分、评论和基本信息。我们分别展示了通过IMDb API和两种方法抓取数据,并进行了数据存储、分析与可视化。在未来,我们还可以基于这些数据开发电影推荐系统、情感分析工具等,进一步丰富电影数据的应用场景。通过这些实践,您不仅学会了如何抓取和存储数据,还可以通过这些基础来构建自己的数据分析应用,获取更丰富的电影数据。

2201_76125261的博客 601

Haskell 学习笔记(二)

Haskell 类型类型声明单参数例子多参数例子Int 和 Integer类型变量type variableshow 和 readboundNum Haskell有一个静态类型系统。每个表达式的类型在编译时都是已知 Haskell 可以自己推断数据的类型 :t 可以来判断表达式的类型 Prelude> :t 'a' 'a' :: Char Prelude> :t True True ...

weixin_44490062的博客 393

第7章: MMU notifier在AMD GPU驱动中的应用

AMD GPU驱动利用MMU Interval Notifier机制实现共享虚拟内存(SVM)和异构内存管理(HMM)。通过分析AMDGPU内存架构(VRAM、GTT、Userptr)和Buffer Object设计,重点探讨了Userptr零拷贝机制如何依赖MMU notifier保持CPU/GPU内存一致性。HMM框架进一步实现统一地址空间和透明页面迁移,AMDGPU通过amdgpu_hmm.c实现两种invalidate回调(GFX和HSA模式),处理不同场景下的内存失效同步问题。

图形/计算GPU的驱动与虚拟化技术分享园地 2473

FC7300 SPI MCAL配置引导

Example - QMI8A01z外设:Example - QMI8A01z外设:

舊梦的博客 260

Haskell学习笔记 --- GHCi中如何敲入多行代码

Haskell学习笔记 --- GHCi中如何敲入多行代码

杨鑫newlife的专栏 3453

互联网人提高效率必备软件合集

很多的时候我们解决不了问题,只是因为没有找到对的工具,实际上,很多好的工具就在那里,只是你不用而已。这点上,信息壁垒是一个很大的原因,因此我希望兄伙伴们多出去走走,不要只是局限在一个圈层;

zhonglunshun的专栏 3484

【Haskell】Haskell学习笔记 总目录

本文主要是对《Haskell函数式编程入门》读书笔记的目录索引。

memcpy0的博客 418

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

《Haskell趣学指南》读书笔记(2):Type And Typeclass

前言:Haskell同python类似,支持类型推导,不需要额外告知数据类型。现在我们将理解haskell的类型系统 Type相关 || :t 命令 检测表达式的类型 Prelude> :t "aaa" "aaa" :: [Char] (tip: " :: " 读作 “它的类型”) 下面我们研究 符号 —> :: || “ :: ” 用于函数类型声明 mylast :: [a] ->a --类型声明 mylast[] = error"empty list" myla

fang 0 jun的博客 639

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

【读书笔记】Haskell函数式编程入门 I 基础篇 1. Haskell简介

文章目录1. Haskell简介1.1 Haskell的由来1.2 Haskell编译器的安装以及编写环境1.3 `.hs` 文件和 `.lhs` 文件、注释与库函数1.4 第1个Haskell程序——HelloWorld 1. Haskell简介 这一节太简单了,放在本文吧。本章内容只有4个: 介绍从Lisp诞生,到多种函数式编程语言的出现,到Haskell的出现和发展; 安装Haskell编译器,构建相应语言环境; Haskell的两种源代码文件,它们的区别; 编写一个HelloWorld程序 1.

memcpy0的博客 1349

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

programming in haskell 读书笔记1

本人转载自这里,记录下haskell一些简单的基础,大牛轻拍。 haskell 中有+ - * / ^ 和 `div` (这个是只取整数部分,比如 5 'div'3 输出 1   其他的符号就不用解释了。  这边要注意一些算符优先级, 比如2*3^4 相当于 2*(3^4) ,而2^3^4相当于 2^(3^4)。  haskell中还有很多操作list的操作。  (1) 选择

kizab的专栏 597

《Haskell趣学指南》读书笔记(1):Ready Go

体外话: 修改命令行提示"prelude"的命令为: :set prompt "xxx" 函数相关 || 函数书写的语法 ||| 命令行中写函数 ( 注意:在命令行中的函数声明,若没有参数,则等价于变量的初始化,称其为“定义”) doubleMy x = x + x; ||| 在编辑器中写函数: 用任一编辑器在文件中写函数 :l 文件名 --加载文件中的函数 || 函数名的规则:函数名不允许首字母大写 || 函数中的选择条件语句:注意haskell中if与else必须同时出现(不能只写if) doubl

fang 0 jun的博客 387

Learn Haskell(一)

这一系列博客是《Learn You a Haskell for Great Good》的读书笔记。 一句话介绍:Haskell是一门纯粹的函数式编程语言。至于什么是函数式编程?尽管网上也有很多关于函数式语言与指令式语言之间的区别与联系,但是没有实际使用过函数式编程语言的情况下,我也搞不清楚。因此,先从学习一门函数式编程语言开始吧。 1.安装Haskell要开始使用Hask...

wawlian说 207

Programming In Haskell 读书笔记1

书里面用的是huge我用的是GHC 1 首先到 http://haskell.org/ghc/ 这边去下载个haskell的 编译器。 如果不习惯emacs的话可以到[url=http://eclipsefp.sourceforge.net/haskell/index.html]这里[/url] 去下个 eclipse的插件,不过要注意这个插件只支持jdk5.0. 2 ...

但行好事 莫问前程 176

【读书笔记】Haskell函数式编程入门 I 基础篇 2. 类型系统和函数

adfqrqwt

memcpy0的博客 1243

《Learn You a Haskell for Great Good!》读书笔记(三)

这是7,8,9章的一个小结; 实际上我看完这3章花了相当长的时间,一来最近工作的事情比较忙,二来这3章实际上包含了众多的how to,一些用法上的新玩意儿都迸发了出来...并且如果是第一次接触这语言的话,最好敲一敲那些代码,才能期望有个“感觉”;重点主要集中在type和typeclass的深入概念上,看这段内容的时候一定要不惜花时间思考,实际上我花了相当长的时间思考typeclass和type之...

pf_miles的专栏 258

【Real World Haskell】读书笔记 1.Getting Started

很长一段时间没有来博客园了,也不是这段时间很忙。只是一下子不知道该做什么,整日除了电影、小说之外,就是睡觉,生命似乎失去了光彩。 可能是因为毕业以后就要出去工作,这种转变有点不太适应。学校的生活让我厌倦,精神无处栖息,惶惶不可终日。 毕设摆在那里也不想理会,提不起兴趣,更别提毕设之外的东西。也许摆脱现在这种困境的一种方式,就是找点事情做,不要考虑做什么...

weixin_34198797的博客 192

real world haskell -读书笔记

[code="haskell"] Prelude> :type map map :: (a -> b) -> [a] -> [b] [/code] [list] [*] -> 右结合 所以 (a -> b) -> [a] -> [b] == ((a -> b) ->( [a] -> [b])) [*](a->b) 输入为a类型,返回b类型的函数A; [*]( [a] -> [b]))...

善待人生,笑对生活... 150

《Haskell趣学指南》读书笔记(3):函数的语法

本章着手于Haskell独特的语法结构 模式匹配 lucky :: (Integral a) => a -> String lucky 7 = "Lucky Number" lucky x = "sorry" 调用lucky时。模式会从上到下进行依次模式匹配,匹配成功则自动运行该句话,匹配失败则自动转到下一句模式匹配 --阶乘 (模式匹配中也可以使用递归) factorial :: (Integral a) => a -> a factorial 0 = 1 facto

fang 0 jun的博客 260

《Learn You a Haskell for Great Good!》读书笔记(一)

[url=http://learnyouahaskell.com/]这里[/url] 就是那本“书”了; 在线版的,周末看了1,2,3,4,5章,做个小记录吧,狠有意思; 这里准备记些个...那个...点,不是每点都记,也不需要每点都记,总体来讲haskell程序还是基于灰常一致的规则运行着的(binding & applying),我想记的只是一些内建函数的备忘、special form和...

pf_miles的专栏 380
上一篇: C++ 实现多线程快排
下一篇: 读书笔记-《操作系统真象还原》-第0章 一些你可能正感到迷惑的问题
dalerkd
博客等级 码龄14年 274粉丝 304原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值