Haskell学习笔记

摘要:
…高阶函数映射:bool)->使用函数f过滤序列[a];Lambda著名的Lambda表达式(在C++11中引入)。遍历列表中的元素并相应返回值的所有操作都可以交给fold来实现。列表的head元素将自动用作初始值。它可以简单地写成sqrt$1+2+3函数。复合函数的组合对应于数学中的复合函数。它只是不那么优雅。第七章,模块,前六章主要介绍功能。

…高阶函数

map :: (a->b) ->[a] ->[b],将函数f依次应用于序列[a],得到新的序列[b]。

filter :: (a->bool)->[a]->[a],利用函数f过滤序列[a]。

这两个函数都可用list comprehension来实现,不过在某些情况下更简洁。利用这两个函数和CF组合可以生成各种需要的函数。

lambda

著名的lambda表达式(C++11中引入),也就是匿名函数,某些仅使用一次的函数不必命名,为了使代码更简洁,就有了lambda表达式。其格式为:

\ para1 para2->(return value)

\ (para1,para2) -> (return value)

由于Haskell有自动类型推断,所以不必明确表明返回类型。注意这里直接return value了,也就无法使用模式匹配之类的。

折叠

折叠是对list处理模式的再抽象。所有遍历list中元素并据此返回一个值的操作都可以交给fold实现。

foldl即为左折叠,从list左端开始。其参数分别是一个二元函数(参数分别是新值、累加值),一个初始值,一个待处理的list。

foldr为右折叠,由于模式匹配的时候一般不使用++,这时候就会用:配合foldr来完成任务。另外foldr适合处理无限长的list。

foldl1将参数中的初始值去掉,自动以list的head元素作为初始值;foldr1类似,取的是最后的元素。

scanl、scanr与fold系列类似,只是累加值的状态会被记录到下一次累加中(sum即scanl (+))。

$

$是函数调用符,与空格不同的是它的优先级最低,且为右结合,设计这个操作符的目的只是让某些函数写起来更简单。比如 sqrt (1+2+3),可以简单写成sqrt$1+2+3

函数组合

函数组合对应着数学中的复合函数。如果想要生成新的函数,使用函数组合操作符"."可能会很方便。"."具有右结合性,右边函数的返回值类型必须与左边函数的参数值类型相符。它的作用类似于管道操作符,将先进行的运算结果传给前面的函数。显然函数组合只适用于只有一个参数的函数之间。一般也是用于简洁化书写。

Haskell是偏于数学的高等抽象语言,因此以上这些特性内置在语言中,只是给coders提供了一些更优雅的书写方式,用前面学过的list comprehension都可以完成相同的功能,只是没有那么优雅了╮(╯-╰)╭

第七章 模块

前面六章主要介绍了函数,身为FP,函数显然是最重要的组成部分。但是作为一门编程语言,一些必备的特性也会出现在Haskell中,例如:库。

Haskell中的模块是由一组相关的函数,类型和类型类组成的。程序的架构就是由主模块调用其他模块(类似C),前面介绍的函数都是装载在prelude中的。

导入模块的语法类似java,import xxx(在ghci中是:m xxx,可以一次导入多个),如果只是导入一部分函数,可以在模块名后面在上(fun1,fun2..),如果要去除某一函数,可以在模块名后面加上hiding (funx),后者主要是为了避免命名冲突。

避免命名冲突还有一个方法,就是加上限定符(类似C++),使用import qualified module_name as name1,关键字 qualified表面后面的模块必须加上限定名,as则可以为限定符起别名。 下面介绍标准库的常用模块:

Data.List

显然这里是前文介绍的所有list操作函数所在的库。下面是一个简表:

函数原型

解释

intersperse :: a- > [a]- > [a]

将第一个参数插入list相邻的元素之间

intercalate :: [a] -> [[a]] -> [a]

将第一个List交叉插入第二个List中间

transpose :: [[a]] -> [[a]]

反转一组List的List,类似转置矩阵

foldl' & foldl1'

非惰性版的foldl和foldl1,大list的时候用

concat :: [[a]] -> [a]

合并list中的元素,可用来追加字符串

concatMap :: (a -> [b]) -> [a] -> [b]

map一个list,然后concat

and(or) :: [Bool] -> Bool

对一组bool做与(或)运算

any(all) :: (a -> Bool) -> [a] -> Bool

一组元素中满足条件的元素存在(都是)

iterate :: (a -> a) -> a -> [a]

用参数2递归调用参数1,产生无限的list

splitAt :: Int -> [a] -> ([a], [a])

在指定下标处切割list,返回一个tuple

takeWhile :: (a -> Bool) -> [a] -> [a]

将满足条件的前面连续多个元素提取出来

dropWhile :: (a -> Bool) -> [a] -> [a]

将前面不满足条件的连续多个元素舍弃

span(break) :: (a -> Bool) -> [a] -> ([a], [a])

类似takeWhile,不过将结果切割了,分别从false处、true处断开

sort :: Ord a => [a] -> [a]

排序,以<顺序

group :: Eq a => [a] -> [[a]]

将相邻并相等的元素分组,配合sort

inits(tails) :: [a] -> [[a]]

递归调用init(tail)直到什么都不剩

isInfixOf :: Eq a => [a] -> [a] -> Bool

子序列判定,isPrefixOf、isSuffixOf用于判定首尾序列

elem、notElem

判定是否子元素

partition :: (a -> Bool) -> [a] -> ([a], [a])

过滤元素并分组

find :: (a -> Bool) -> [a] -> Maybe a

返回第一个满足条件的元素

elemIndex :: Eq a => a -> [a] -> Maybe Int

返回第一个相等元素的索引

elemIndices :: Eq a => a -> [a] -> [Int]

返回所有满足条件元素的索引集

findIndex :: (a -> Bool) -> [a] -> Maybe Int

返回第一个满足条件元素的索引

findIndices :: (a -> Bool) -> [a] -> [Int]

返回所有满足条件元素的索引集

zip,zipWith系列(<=7)

将list对应元素组合成tuple的list

lines :: String -> [String]

将字符串按行分割

unlines :: [String] -> String

line的反函数

words(unwords)

合并单词集或相反

nub :: Eq a => [a] -> [a]

去除所有重复元素,组成新的list

delete :: Eq a => a -> [a] -> [a]

删除第一个与之相等的元素

union(intersection) :: Eq a => [a] -> [a] -> [a]

返回两个list的并(交)集,以第一个为主顺序

insert :: Ord a => a -> [a] -> [a]

保持顺序的插入元素

  

以上函数中,参数为int的都有更通用的版,在前面加上genernic就可得到通用版(如genericLength);

而用(==)判定相等的函数,可以改成用谓词作判定依据,只需要在其后加上By,如sortBy,groupBy等。

这里引入了Data.Function中的on函数:on :: (b -> b -> c) -> (a -> b) -> a -> a -> c

f `on` g = \x y -> f (g x) (g y),这个函数可以使By系列的函数使用起来更加简洁。判断相等性常用 (==) `on` xxx,判定大小则常用 compare `on` xxx.

Maybe类型是在可能返回nothing时使用,这样返回时如果存在就用Just xxx的格式,否则返回Nothing

Data.Char

这个模块主要包含了一些字符处理函数。类似于C中的<ctype.h>

函数原型

解释

isControl :: Char -> Bool

判断控制字符

isSpace

判断空格字符(space、tab、\n)

isLower

判断小写字符

isUpper

判断大写字符

isAlpha(isLetter)

判断字母

isAlphaNum

判断字符或数字

isPrint

判断可打印字符

isDigit(isNumber)

判断数字

isOctDigit

判断八进制数字

isHexDigit

判断十六进制数字

isMark

判断Unicode注音(for Frenchman)

isPunctuation

判断标点符号

isSymbol

判断货币符号

isSeperater

判断Unicode空格或分隔符

isAscii

判断unicode字符表前128位

isLatin1

判断unicode字符表前256位

isAsciiUpper

判断大写ascii字符

isAsciiLower

判断小写ascii字符

generalCategory :: Char -> GeneralCategory

判断所在分类

toUpper :: Char -> Char

小写转换成大写,其余不变

toLower

与上面相反

toTitle

将一个字符转换成title-case

digitToInt(ord)

字符转换成int值

intToDigit(char)

int转换成字符

注意这里的函数比C中的字符处理函数要多得多,除了考虑unicode因素外,这里将各种进制的数看做完全不同的东西。也就是说,并不依据计算机内存模型。

Data.Map

这里的map类似C++中的关联容器std::map.一个list里面全是pair(两位的tuple)。内部构造是由红黑树完成的,键值必须可排序。

函数原型

解释

fromList :: Ord k => [(k, a)] -> Map k a

将一个关联列表转换成一个map

insert :: Ord k => k -> a -> Map k a -> Map k a

插入一对键值

empty :: Map k a

返回一个空map

null :: Map k a -> Bool

测试一个map是否非空

size :: Map k a -> Int

返回map大小

singleton :: k -> a -> Map k a

由参数构建一个pair(Haskell学习笔记第1张std::make_pair)

lookup :: Ord k => k -> Map k a -> Maybe a

查找键,找到后返回对应的值

member :: Ord k => k -> Map k a -> Bool

查找键是否存在

map、filter

类似list中的函数,只针对value(与key无关)

keys、elems

返回由key或者value组成的list

toList :: Map k a -> [(k, a)]

由map生成对应的list

fromListWith :: Ord k => (a -> a -> a) -> [(k, a)] -> Map k a

类似于multimap,可以由一个key对应多个键值,参数1选择key值相同的键如何处理

insertWith :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a

insert的复数版,如果存在相同key,由参数1决定如何处理value

Data.Map里面还有不少函数,常见的操作已经都列举在上面了。

Data.Set

与STL::set类似的数据结构,键值唯一。

函数原型

解释

fromList :: Ord a => [a] -> Set a

与map中的类似,将list转化为set

difference :: Ord a => Set a -> Set a -> Set a

返回第一个有第二个没有的元素集

union :: Ord a => Set a -> Set a -> Set a

取并集

null,size,member,empty,singleton,insert,delete

与map的接口功能类似

isSubsetOf :: Ord a => Set a -> Set a -> Bool

判断是否子集

isProperSubsetOf :: Ord a => Set a -> Set a -> Bool

判断是否真子集

map和filter

也类似于map

这里还讨论了Data.List.nub的执行效率问题,nub要求List元素具有Eq类型类,而要使用集合来去除重复元素,必须是Ord类型类。后者的执行速度比前者,前者在大list时不如setNub(但是setNub不稳定)。

自定义模块

自定义模块的模块名与文件名必须一致(这点类似matlab中的.m文件)。格式是:

module Xxx

(fun1,fun2..)

where fun1 :: a->b->c

    fun1=…

    fun2::…

注意模块名首字母大写。如果要采用分层的方法,则新建一个文件夹,为模块名(如Data),然后建文件(如List),导入时把整个文件夹放在引用它的文件的同一目录下。注意声明的时候前面要加上限定符(如module Data.List)。

虽然module看起来很类似C中间的Struct,但是还是有本质的不同,最明显的就是它只封装了一系列的函数,而C中间则只能存放变量。另外就是Haskell并不支持面向对象。

免责声明:文章转载自《Haskell学习笔记》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ASP.NET中WebService的两种身份验证方法Stanford机器学习笔记-1.线性回归下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

CSS之显示天气

 这个可以有,自从有了这个,以后查询天气就方便多了,哈哈。 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <head> <titl...

windows下的shellcode剖析浅谈[转自看雪]

标 题: 【原创】windows下的shellcode剖析浅谈作 者:snowdbg时 间: 2009-10-06,11:12链 接: http://bbs.pediy.com/showthread.php?t=99007  今天是中秋节,正好我的文章在今天基本完成,作为中秋礼物送给大家,由于本人水平有限希望大家多多批评指正!学习了好些日子了,思路总是乱...

微信 ios端config配置失败 android端正常

<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> 如果你页面启用了https,务必引入 https://res.wx.qq.com/open/js/jweixin-1.0.0.js ,否则将无法在iOS9.0以上系统中成功使用JSSDK...

SqlServer性能急剧下降,查看所有会话的状态及等待类型---Latch_Ex

      当某个数据库文件空间用尽,做自动增长的时候,同一时间点只能有一个用户人员可以做文件自动增长动作,其他任务必须等待,此时会出现Latch资源的等待。使用sp_helpdb查看业务数据库时发现:该数据库设置不合理,数据文件每次增长2M,日志文件每次增长10%,且分别设置了最大限制。修改为每次增长200M,不限制大小,系统恢复正常,问题解决。 Sql...

java List接口一

一 List接口概述   查阅API,看List的介绍。有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的 插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的 元素。与 set 不同,列表通常允许重复的元素。 看完API,我们总结一下:   List接口:   它是一个元素存取有序的集合...

ehcache.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- CacheManager Configuration ========================== An ehcache.xml corresponds to a single CacheManager. See instructions...