本周读完了 Haskell 入门文档,这里做一下笔记。
一、变量类型
变量
与命令式语言不同,Haskell 同一作用域内变量值不可改变。
r = 5
r = 2 -- error: multiple declarations of r
复制代码
由于同一作用域变量值不可改变,所以变量定义可以是任意次序。
-- 如下的两种定义是等价的
-- A
y = x * 2
x = 3
-- B
x = 3
y = x * 2
复制代码
递归定义
-- 与命令式语言不同,如下的代码是递归定义变量,而不是变量加1
r = r + 1
复制代码
作用域,函数参数的作用域和函数定义的作用域不同(和其他语言类似)。
Prelude> let r = 0
Prelude> let area r = pi * r ^ 2 -- 调用时 r == 5 而不是等于 0
Prelude> area 5
78.53981633974483
复制代码
类型
布尔(Bool)
取值:True
False
Prelude> 2 + 3 == 5
True
Prelude> 7 + 3 == 5
False
复制代码
运算符: <
<=
==
>=
>
;||
&&
not
Prelude> (3 < 8) && (False == False)
True
Prelude> not (5 * 2 == 10)
False
复制代码
不支持不同类型的比较
Prelude> 2 == True
<interactive>:1:0:
No instance for (Num Bool)
arising from the literal ‘2’ at <interactive>:1:0
Possible fix: add an instance declaration for (Num Bool)
In the first argument of ‘(==)’, namely ‘2’
In the expression: 2 == True
In an equation for ‘it’: it = 2 == True
复制代码
中缀表达式和前缀表达式
Prelude> 4 + 9 == 13
True
Prelude> (==) (4 + 9) 13
True
Prelude> (3 < 8) && (False == False)
True
Prelude> (&&) (6 <= 5) (1 == 1)
False
复制代码
数字
Int
: 整数,32位机器上范围 -2147483648 to 2147483647;Integer
:任意大小,会有性能开销;Double
:双精度浮点数。
字符和字符串
字符(Char):单引号;
Prelude> :t 'H'
'H' :: Char
复制代码
字符串(String/[Char]):双引号;
-- 实际上就是字符列表,String 是 [Char] 同义词
Prelude> :t "H"
"H" :: [Char]
复制代码
字符串拼接:++
Prelude> "H" ++ "H"
"HH"
复制代码
列表和元组
-
列表元素必须是同类型;
-
列表拼接:
:
Prelude> let numbers = [1,2,3,4] Prelude> numbers [1,2,3,4] Prelude> 0:numbers [0,1,2,3,4] Prelude> 1:0:numbers [1,0,1,2,3,4] Prelude> 2:1:0:numbers [2,1,0,1,2,3,4] Prelude> 5:4:3:2:1:0:numbers [5,4,3,2,1,0,1,2,3,4] Prelude> "hey" == ['h','e','y'] True Prelude> "hey" == 'h':'e':'y':[] True 复制代码
-
元组元素个数不可改变;
-
元组元素无需同类型;
(True, 1) ("Hello world", False) (4, 5, "Six", True, 'b') 复制代码
二、条件语句
Haskell 的条件语句除了其他语言中的 if-else,还有 Guards 和 piece-wise definition 两种形式。
if / then / else
mySignum x =
if x < 0
then -1
else if x > 0
then 1
else 0
复制代码
Guards
mySignum x
| x < 0 = -1
| x > 0 = 1
| otherwise = 0
复制代码
piece-wise definition
pts :: Int -> Int
pts 1 = 10
pts 2 = 6
pts 3 = 4
pts 4 = 3
pts 5 = 2
pts 6 = 1
pts _ = 0
复制代码
三、函数
Haskell 函数中,无论定义和调用,参数两边的括号可省略,括号仅用来组合表达式。
签名和定义
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
复制代码
调用
xor True False -- output: True
复制代码
四、输入输出
-- TODO:
复制代码
五、其他
注释
-
单行注释
--
;x = 5 -- x is 5. y = 6 -- y is 6. -- z = 7 -- z is not defined. 复制代码
-
多行注释
{- ... -}
;answer = 2 * {- block comment, crossing lines and... -} 3 {- inline comment. -} * 7 复制代码
GHCi 命令
-
:quit/:q
:退出 GHCi;Prelude> :quit Leaving GHCi. 复制代码
-
:load/:l
:加载模块;Prelude> :load Varfun.hs [1 of 1] Compiling Main ( Varfun.hs, interpreted ) Ok, modules loaded: Main. 复制代码
-
:reload/:r
:重新加载模块;*Main> :reload Compiling Main ( Varfun.hs, interpreted ) Ok, modules loaded: Main. *Main> 复制代码
-
:type/:t
:判断变量类型;Prelude> :type True True :: Bool Prelude> :t 1 1 :: Num p => p 复制代码
源码文件
以 .hs
为后缀,例如:Varfun.hs。