系列文章
- 《Haskell趣学指南》笔记之基本语法
- 《Haskell趣学指南》笔记之类型(type)
- 《Haskell趣学指南》笔记之函数
- 《Haskell趣学指南》笔记之高阶函数
- 《Haskell趣学指南》笔记之模块
- 《Haskell趣学指南》笔记之自定义类型
- 《Haskell趣学指南》笔记之I/O
这本书居然没有告诉我怎么加注释,我自己搜了一下
- 单行注释以
--
开头 - 多行注释用
{- whatever -}
括起来
继续看书
显式类型声明
:t <exp>
可以得到对应的类型- 类型是大写字母开头的
- 给单参数函数声明类型,语法是
:: ParamType -> ReturnType
removeNonUppercase :: [Char] -> [Char] removeNonUppercase st = [ c | c <- st, c ` elem` ['A'..' Z']]
- 给多参数函数声明类型,语法是
:: Param1Type -> Param2Type ->ReturnType
addThree :: Int -> Int -> Int -> Int addThree x y z = x + y + z
基本类型
- Int -- 有界
- Integer -- 无界,可以存超大整数,效率比 Int 低
- Float / Double / Bool / Char / String就是[Char]
- tuple 的类型由其内部的元素类型决定,空 tuple 是一个单独的类型,只有一个值
()
类型变量(类似于泛型)
- head 的类型是
head :: [a] -> a
- 注意这里的 a 是小写,不是大写,因为 a 是类型变量,不是类型
- 一般类型变量只使用一个字母,但是用多个字母也不报错
- 多态函数:使用了类型变量的函数。
类型类 typeclass
- 类似于接口,但是它是用来约束类型 type 的。
- 一个 type 可以是多个 typeclass 的实例,一个 typeclass 可以有多个 type 实例。
- Eq 是最常见的类型类,Haskell 中标准类型都是 Eq 的实例,Eq 要求它的实例必须实现
==
和/=
两个函数 - 我们可以看看
==
运算符(也是函数)的类型ghci> :t (==) (==) :: (Eq a) => a -> a -> Bool
- 看上面代码,类型声明
a->a->Bool
前面有个=>
,再前面有个(Eq a)
- 这个
(Eq a)
叫做类型约束 - 它约束 a 必须是 Eq 的实例,这样就保证了 a 必须实现
==
函数,以提供给全局的==
函数调用
- 这个
- Ord 类型类要求实例必须实现
< / <= / > / >=
等比较操作 - Ord 的有三种值:GT / LT / EQ,可以用 compare 得到
ghci> compare 1 2 LT
- Show 类型类要求实例可以表示为字符串
- show 函数可以把任意 Show 实例变为字符串
- Read 类型类跟 Show 相反,它把非字符串的东西转为字符串
- read 函数是 show 的相反操作
ghci> show True "True" ghci> (read "True") || False True
- 注意直接
read "True"
会报错,因为 GHCi 需要根据后续的操作来确定你要把字符串转成什么类型 - 类型注解:可以使用类型注解来告诉 GHCi 这玩意是什么类型。
read "True" :: Bool
就不会报错,看起来很像 TypeScript 的 as 关键字 - Enum 类型类要求实例有 successer 后继和 predecesor 前趋两个操作。可以使用 succ 函数和 pred 函数得到一个实例的后继和前驱。
- Enum 的例子
['a' .. 'e']
-- "abcde"[LT..GT]
-- [LT, EQ, GT]
- Bounded 类型类要求实例有上限和下限
- 用 maxBound 和 minBound 可以获取实例的上下限
- 这两个函数的类型是
(Bounded a)=> a
,这叫多态常量(跟多态函数对应)。 maxBound :: (Bool, Int, Char)
会得到每个实例的上限组成的 tuple,即(True, 2147483647, \1114111)
- Num 类型类要求实例具有数的特征。
:t 20
的结果是(Num t)=> t
- 这很奇怪, 20 的类型居然不是 Int 或者 Integer 或者 Float 之类的,而是这些类型对应的 typeclass 对应的多态常量,有点烧脑。
- 所有的数都是多态常量,可以具有任何 Num 的实例的特征,也就是说 20 既可以是 Int / Integer 也可以是 Float / Double 等。
- Floating 类型要求实例具有浮点数的特征,如 Float 和 Double 都是 Floating 的实例。
- 如
sin :: Floating a => a -> a
- Integeral 类型要求实例具有整数的特征,如 Int 和 Integer。
- 如
fromIntegral :: (Num b, Integral a) => a -> b
length [1,2,3] + 3.2
会报错,解决办法是fromIntegral (length [12,3]) + 3.2
类型类概览
- Haskell 中所有标准 type 都是 Eq 的实例,除了输入输出相关类型和函数
- 目前我们遇到的所有 type 都是 Ord 的实例,除了函数
- 目前我们遇到的所有 type 都是 Show 的实例,除了函数
- 目前我们遇到的所有 type 都是 Read 的实例,除了函数
- Enum 类型类包含的 type 有 () / Bool / Char / Ordering / Int / Integer / Float / Double
- Bounded 包含的 type 有 Int / Char / Bool 等
- Num 包含 Int / Integer / Float / Double,只有已经属于 Show 和 Eq 的类型实例,才能成为 Num 的实例,这是一个先决条件( prerequisite)
- Floating 包含 Float / Double
- Integeral 包含 Int / Integer