Haskell
2016-08-28 本文已影响0人
非作者
[TOC]
Haskell
GHCI
- 通过Tab可以自动补全
- 通过
:browser 模块名称
,浏览该模块下的函数 -
:info 函数名
显示函数相关信息 -
:set +t
每次输出都会携带输出类型信息
标准库函数
map
遍历数组,针对数组中的元素进行映射转换处理;映射转换是有一个函数组成的
-- (\x -> x ^2 ) 表示定义了一个匿名函数(lambda 表达式)
-- 从[1..10] 这个数组中取出每一个元素,传给匿名函数,x则表示的就是传入的元素
-- 针对传入的元素做平方操作后放回到数组中
map (\x -> x ^2 ) [1..10]
-- out: [1,4,9,16,25,36,49,64,81,100]
filter
遍历数组,针对数组中的元素进行过滤判断处理;过滤判断函数必须返回值为Bool类型
filter (\x -> x `mod` 3 == 0 ) [5..25]
-- out : [6,9,12,15,18,21,24]
lambda 表达式
用
\
作为开始,并且需要用括号包裹;->
之前的是参数,多个参数用空格分隔,之后的表示函数体;
关键字 fold
针对数组进行左右折叠操作
foldl/foldr scanl/scanr
foldl 左折叠操作 foldr 右折叠操作
scanl 记录折叠操作状态,相当于是foldl的执行过程记录
foldl1 foldr1 相比fold1 少了累计值,其实累计值用的是数组的第一个元素
scanl1 scanr1
-- foldl :: (b -> a -> b) -> b -> [a] -> b
-- (+) 对应 (b -> a -> b) 表示 加函数 对应 b 和 a两个参数并且返回 b类型
-- 0 对应 -> b 表示的是累计值
-- [1..10] 对应 -> [a] 表示的是数组
-- 输出值 对应 -> b
-- 整体过程: 用 0+1的结果作为 累计值,再加 2 ,依次类推
foldl (+) 0 [1..10]
--out: 55
scanl (+) 0 [1..10]
--out: [0,1,3,6,10,15,21,28,36,45,55]
含有$ 的函数
$ 用来断开整个函数,以使得 $ 的右侧先执行,意义在于函数都是从左到右的优先级;
$ 的优先级最低,一定程度上可以减低括号的使用
-- 表示 5 * (2+7)
(*) 5 ((+) 2 7)
-- 两者等同,如去掉 $ 则无法正确执行
(*) 5 $ (+) 2 7
-- out: 45
-- 此处表示用$ 可以将数据作为函数调用
map ($ 3) [(4+),(10*),(^2),sqrt]
-- out : [7.0,30.0,9.0,1.7320508075688772]
Function composition 函数组合
函数组合就是多个函数组合成一个串行的函数链,用 点号(.) 进行连接;
组合函数是前一个函数的参数类型需要同后一个函数的回传值类型一致
fx (fy (fz p)) 使用组合方式为 (fx . fy . fz) p,fz p执行后的返回值类型需要同fy的参数类型一致
不建议使用组合方式,形成复杂的函数链条,可以拆分成多个子函数链,使用let绑定一个函数名称,可以提高代码可读性
4 + (3*4)
-- 使用函数的方式编写 $表示先执行 3 *4
(+) 4 $ (*) 3 4
-- 使用点号组合函数,组合函数
-- +4 和 *3 都是一个不完全函数,相当于是都只传了一个参数的函数
-- 先将参数 4 传给 *3 ,然后将结果 12 传给 +4 ,所以得到16
((+4) . (*3)) 4
(+4) . (*3) $ 4
let sx = (+4) . (*3) in sx 4
-- out: 16
Module 模块
模式是含有一组相关的函数、型别和型别类的组合;
-- import 用于在代码中装载模块
-- qualified 显示代码中需要引用某函数时需要加上 Data.Map前缀,为了解决加载模块中函数名冲突的情况
-- as M,则是简写 Data.Map前缀 为M
import qualified Data.Map as M;
构建模块
-- 以hs文件名 构建模块
module fileName
( functionName1,
functionName2,
functionName3
) where
-- 以hs文件所在目录,构建子模块
module fileDir.fileName
( functionName1,
functionName2,
functionName3
) where
构建Types 和 Typeclasses
data Shape = Circle Float Float Float | Ractangle Float Float Float
Record Syntax
Type parameters 型别参数
类似java 里面的泛型,针对型别不固定的情况,可以用型别参数的方式达到更好的通用性
-- Map 就是携带了 k v 两个型别参数
import qualified Data.Map as Map
Derived instances
deriving (Eq, Ord, Show, Read, Bounded, Enum)
- Eq 比较
- Ord 排序
- Show 显示成字符串
- Read 解析成具体的型别
- Bounded 边界
- Enum 枚举
Type synonyms
型别同义词,相当于给型别取了个别名
-- String 就是字符数组的别名
type String = [Char]
Recursive data structures (递归地定义数据结构)
在定义型别时,值构造子又使用了定义的型别,形成递归
-- 模拟标准库中的List的递归
data List a = EmptyList | Cons { listHead:: a, listTail :: List a } deriving (Show,Read,Eq,Ord)