日志

Haskell复习笔记(一)

 来源    2018-09-17    0  

Haskell笔记这是第三次总结,前两次都因为各种原因丢失了,对于Haskell我算不上什么大神,只不过在大学时为了学习算法时选择了Haskell。

当时的入门书籍选择的是《Learn You Haskell》,如果你对Haskell有兴趣,它会是一个很好的选择。

编译器来这里下载https://www.haskell.org/downloads

什么是Haskell?

Haskell是一种纯函数式编程语言,在生产环境中使用的较少。

  -  Haskell的变量一旦定义就不会更改,比如定义变量x=5,那么变量x在程序中就只能是5,不能赋其他值。

  -  Haskell是惰性的,在Haskell中如果定义了一个函数,在真正需要接过前是不会求值的,比如在我们遍历一个list求和时,它会得出一个超长的加法算式,省去了一步步计算加法的时间。

  -  Haskell是静态类型的,在编译程序时,需要明确数据类型,同时拥有自动类型推导,类 似于python,比如定义变量a = 3+4,那么默认a就是一个整型,不需要定义。

  -  Haskell的代码量更少,很容易维护和读懂别人的代码。

Haskell的基本数据类型

Haskell的运算符和逻辑判断语句

基本的加减乘除没什么区别,在/运算时,返回的是浮点数

- bool代数

- True和False表示真和假。

- &&表示and(和),||表示or(或)。

- 逻辑判断语句在haskell中可以看作一个表达式使用,基本的结构是 if...then...else...,和其他语言不同的是,Haskell的then和else都要返回结果,并且不能省略。

- int表示整数,上限是2147483647,下限是-2147483648

- integer表示无限整数。

- float表示单精度的浮点数

- double表示双精度的浮点数

- bool表示布尔值,True和False。

- char表示一个字符,一组字符作为元素的list即为字符串。

List

在Haskell中,List是最常用的数据结构,和python不同的是List是单类型的数据结构,在list中只能存储多个相同类型的元素,比如一组数字。

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

字符串在Haskell中可以看作一组字符的List,如['c','u','i']和'cui'是相同的,只不过'cui'是语法糖的表示。

关于语法糖的定义:语法糖就是把原本复杂的语法结构以简单的方式表现出来,其功能不变。

字符串的合并是由"++"来连接,在对长字符串进行"++"操作时要注意,Haskell会遍历整个list,此时使用:来进行插入会更好。

在Haskell中若想取出数据使用!!,字符串索引从0开始。

"hello"++" "++"world"    #"hello world"
"H":"ello"    #Hello
["hello"]!!0    #hello

在Haskell中List是可以依次比较,进行比较运算的,前提是元素是可以比较的数据类型,Haskell会从头到尾进行比较,如果相等则比较下一个。

[2,3,4]>[2,3]    #True

List的常用函数

- head : 返回list的头部,即首个元素。

- tail :返回list去掉头部剩余的部分。

- last : 返回list的尾部,即最后一个元素

- init : 返回list除了头部剩余的部分。

- length : 返回list的长度

- null :检查list是否为空,返回布尔值。

reverse : 将list反转并返回

take : 返回list的前几个元素,从1开始。

drop :与take相反,它会删除list的前几个元素。

maxinum和mininum :返回list中最大和最小的元素。

sum和product :返回list所有元素的和和所有元素的积。

elem : 判断一个元素是否包含于list,返回一个布尔值。

cycle :接收一个list,并返回一个无限重复原list的list。

range

学过其它语言的肯定不会陌生range,但是在Haskell中range的作用是构造list,这也是单独讲解的原因。

range不是一个函数,它是中文区间,比如[1..20]表示的是元素从1到20的list。

range可以设置不长,如[1,3,..9]表示的就是[1,3,5,7,9],包括但不限于整数,比如字母或者浮点数,但是浮点数的精度在range中可能会出问题,所以避免使用。

list表达式

list表达式是构建list另一种办法,它的基本组成结构是[输出函数 | 变量x的取值范围,变量x的筛选条件]

如取出1到10,小于5能被2整除的元素:[x|x<-[1,10],x 'mod'2==0,x>5]

list表达式的筛选条件可以是一个或多个。

list表达式的取值范围也可使是一个或多个。

Tuple

tuple(元组)一样是一种元素的容器,但是tuple在定义时就已经明确容器内元素的数量了,并且其内元素不必为同样类型。

tuple同样可以进行比较运算,但是相比较的两个元组的长度必须是完全相等的。

tuple最少拥有两个元素,拥有两个元素的tuple也叫做pair。

pair(序对)的常用函数

fst :返回一个pair的首项。

snd :返回一个pair的尾项

zip函数 :可以把两个list合并为元素为序对的list,若两个list的长度不同,则以短的为主。

Type和Typeclasses

 :t命令后跟表达式,会返回它的类型,返回的结构为 表达式::类型,l类型的首字母大写。

类型变量(type variables)

使用到类型变量的函数成为多态函数,如 :t head的返回值是[a]->[a]代表head可以接受任意类型的list并返回它的第一个元素。

typeclasses

typeclasses可以理解为接口,它规定了一系列行为。

- Eq typeclasses 包含所有判断相等性的类型,提供实现的函数是==和/=,所以只要一个函数存在eq的类型限制,那么他定义时肯定==和/=。

- Ord typeclass包含可比较大小的类型,ord内包含了>,<,>=,<=等用于比较的函数,若要成为ord的成员先加入eq家族。

- Show的成员为可用字符串表示的类型,最常用的函数是show,它可以取任何一个成员类型为Show并将其转换为字符串。

- Read会将字符串进行反转,read是其最常用的函数,当回传值类型多时,需要用::来指定回传的类型。如read "4" :: Int

- Enum的成员都是连续的类型,也就是可以枚举,可迭代的,每个值都有后继子和前置子,分别可以通过succ和pred函数的到,Enum包含的类型包括Bool,Char,Ordering,Int,Integer,Float和Double。

- Bounded的成员都有其上限和下线,如Int,Bool。

- Num是表示数字的Typeclass,它的成员类型都有数字的特征。包含所有实数。

- Integral也表示数字,只包含Int和Integer。

- Floating表示浮点类型,Float和Double。

函数的语法

函数式编程语言当然核心就是函数了。

模式匹配

模式匹配从字面上理解就是对  模式   的  匹配,检查传入值是否适合从中取值进行等号后面的计算,使用模式匹配需要经过以下几个步骤。

  - 声明函数的type   格式为 函数名 :typeclass 输入 ->输出

  - 开始匹配模式    格式为   函数名 模式  = 函数体 

chartostr :: Char ->String
chartostr 'a'="a123"
chartostr 'b'="b123"
chartostr 'c'="c123"
chartostr x ="right"

ps:就是模式匹配成功之后执行的函数,haskell一切皆函数,就像字符啊数字啊 都是函数,也可以理解为  = 后面的是回传值

list的匹配模式   (x:y),在匹配模式中没有  ++ 因为无法界定界限,使用会报错

chartostr :: [a] ->String
chartostr (a:[]) = "one ele"
chartostr (a:b:[]) = "two ele"
chartostr (a:b:_)="so long"

还有一种模式叫 as 模式 ,就是用@把模式起个名字,在之后的调用中更方便。

学习Haskell需要记住一句话 变量是变量,参数是参数。

Guards

guard就是士兵,它的特殊点在于其本身就是一个bool表达式,它的函数定义不需要等于号,而是在函数名和参数后面加上 |  函数体是一个比较算式,

maxnum :: (RealFloat a) => a -> String
maxnum x
    | x <5 = "xiaole"
    | x>5="dale"
    |otherwise = "duile"

 可以使用where和let用来绑定变量,不过它们的定义方式和作用域不同,where的作用域是所有的guards,而let只能被使用于定义它的guards,相当于局部变量。

where绑定

和guard的 | 对齐,定义多个变量时,变量需要对齐,=  后面也可以是函数。

where name="cui"
      gender="man"
      age=13
也可以使用模式匹配,看起来很像解构赋值,变为:
where (name,gender,age)=("cui","man",13)

let绑定

let绑定的格式为  let binding in area ,在let定义只对area起作用 ,它是一种表达式。

Prelude> let a = 8 in a + 1

 Case

很多的命令式编程语言都提供了case语句,case与剧中可以使用模式匹配,起始本质上来说,模式匹配就是case表达式的语法糖。比如:

head :: [a] -> a
head [] = "no head"
head [x:_] = x
-- 它们的含义是一样的
head :: [a] -> a
head xs = case xs of [] -> "no head"
                     [x:_] -> x

case表达式可以用在任何地方。

describeList :: [a] -> String
describeList xs = "The list is " ++ case xs of [] -> "empty."
[x] -> "a singleton list."
xs -> "a longer list."
相关文章
Haskell复习笔记(二)
日志Haskell中的递归 递归就是定义函数以调用自身的方式,关于递归解决问题的实例有很多,如斐波那契数列,还有汉诺塔问题,递归也正是Haskell中用来解决循环问题的关键. 自定义maxinum函数 m ...
springmvc复习笔记----文件上传multipartResolver
日志结构                                              web.xml <?xml version="1.0" encoding=&q ...
1
springmvc复习笔记----Restful 风格,PathVariable获取 Url实例
日志结构 包与之前相同 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=&qu ...
springmvc复习笔记----springmvc姓名年龄例子:RequestParam 试水
日志继续 继上节https://www.cnblogs.com/tk55/p/6652394.html  重要部分颜色突出 结构 包 web.xml 乱码处理方面设置 <url-pattern> ...
springmvc复习笔记----springmvc最简单的第一个例子:RequestMapping试水
日志结构 用到的包 web.xml <url-pattern>/</url-pattern>中可以换成其他的后缀*.do ,*. sb  …… <?xml version=& ...
Java复习笔记(二):数据类型以及逻辑结构
日志一.数据类型 1.数据类型又分为基本数据类型和引用数据类型,而他们的区别在于,引用数据类型需要开辟内存空间来进行分配,什么意思呢?先来看看他们有哪些. 整数型:byte,short,int,long ...
mybatis 复习笔记03
日志参考:http://www.mybatis.org/mybatis-3/zh/configuration.html 入门 1. 从 XML 中构建 SqlSessionFactory     每个基于 ...
Spring MVC 复习笔记05
日志1. 上传图片     1.1 springmvc中对多部件类型解析           在 页面form中提交enctype="multipart/form-data"的数据时, ...
Spring MVC 复习笔记04
日志复习 springmvc框架:          DispatcherServlet前端控制器:接收request,进行response          HandlerMapping处理器映射器:根 ...
Spring MVC 复习笔记03
日志1. @RequestMapping     1). url映射          定义controller方法对应的url,进行处理器映射使用.     2). 窄化请求映射            ...
Spring MVC 复习笔记02
日志1. 非注解的处理器映射器和适配器     1.1 非注解的处理器映射器           处理器映射器:org.springframework.web.servlet.handler.BeanNa ...
Spring MVC 复习笔记01
日志1. springmvc框架     1.1 什么是springmvc           spring mvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合 ...
线程池复习笔记
日志1. 线程池是什么?     线程池是预先创建线程的一种技术.线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中.这些线程都是处于睡眠状态,即均未启动,不消耗CPU,而只是占用较小的内存空 ...
杂记复习笔记
日志ThreadLocal 1. ThreadLocal是如何为每个线程创建变量的副本的:     1). 首先,在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的 ...
多线程复习笔记
日志1. 多线程是什么?         线程就是程序中单独顺序的流控制.线程本身不能运行,它只能用于程序中.多线程则指的是在单个程序中可以同时运行多个不同的线程执行不同的任务. 2. 为什么使用多线程? ...
反射复习笔记02
日志注解: 1. 注解是Java 5的一个新特性.注解是插入你代码中的一种注释或者说是一种元数据(meta data).这些注解信息可以在编译期使用预编译工具进行处理(pre-compiler tools ...
反射复习笔记01
日志Java反射: 1. Java反射机制可以让我们在编译期(Compile Time)之外的运行期(Runtime)检查类,接口,变量以及方法的信息.反射还可以让我们在运行期实例化对象,调用方法,通过调 ...
mybatis 复习笔记02
日志1. 一对一查询:         1). 实体类:                2). 定义resultMap <!-- 订单查询关联用户的resultMap 将整个查询的结果映射到cn.i ...
Future复习笔记
日志1. Future就是对于具体的Runnable或者Callable任务的执行结果进行取消.查询是否完成.获取结果.必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果.     Fut ...