Real World Haskell学习篇-第1章: 入门

时间:2022-09-10 16:59:46

1. 初识解释器ghci

  1.1  查看帮助: :?

  1.2  修改提示符: :set prompt ghci>>>

  1.3  加自己指定模块: :module + Data.Ratio

2. 基本交互

  2.1 基本算术运算

    中缀表达式:

1 ghci>>> 3 ^ 3
2 27
3 ghci>>> 2 + 4
4 6
5 ghci>>> 5 / 3
6 1.6666666666666667

    前缀表达式:

1 ghci>>> (^) 3 3
2 27
3 ghci>>> (/) 5 2
4 2.5
5 ghci>>> (+) 1 9

  2.2 算术中的负数

1 ghci>>> -8
2 -8
3 ghci>>> 1 + -4
4 
5 <interactive>:57:1:
6     Precedence parsing error
7         cannot mix ‘+’ [infixl 6] and prefix `-' [infixl 6] in the same infix expression
8 ghci>>> 1 + (-3)
9 -2

-8其实并不是直接表示负数8, 而是利用一元操作符'-'对8取负, 所以第3行不能与中缀表达式一起使用, 除非加上()。

1 ghci>>> 55*-2
2 
3 <interactive>:60:3:
4     Not in scope: ‘*-5     Perhaps you meant one of these:
6       ‘*>’ (imported from Prelude), ‘**’ (imported from Prelude),
7       ‘*’ (imported from Prelude)

这样是另一种不认识的操作符。

  2.3 布尔运算(True False)和比较运算

3种运算符: && || not    Haskell中True不是1, False不是0.

 1 ghci>>> True && False
 2 False
 3 ghci>>> True || False
 4 True
 5 ghci>>> not False
 6 True
 7 ghci>>> True && 1
 8 
 9 <interactive>:75:9:
10     No instance for (Num Bool) arising from the literal ‘111     In the second argument of ‘(&&)’, namely ‘112     In the expression: True && 1
13     In an equation for ‘it’: it = True && 1
14 ghci>>> 1 == 1
15 True
16 ghci>>> 4 > 6
17 False
18 ghci>>> 33 <= 50
19 True

  2.4 运算符优先级和结合性

可以有命令 :info 查看指定操作符的优先级值, 1表示最低, 9 表示最高。

Real World Haskell学习篇-第1章: 入门Real World Haskell学习篇-第1章: 入门
 1 ghci>>> 2 + 3 * 5 ^ 2
 2 77
 3 ghci>>> :info (+)
 4 class Num a where
 5   (+) :: a -> a -> a
 6   ...
 7       -- Defined in ‘GHC.Num’
 8 infixl 6 +
 9 ghci>>> :info (*)
10 class Num a where
11   ...
12   (*) :: a -> a -> a
13   ...
14       -- Defined in ‘GHC.Num’
15 infixl 7 *
16 ghci>>> :info (^)
17 (^) :: (Num a, Integral b) => a -> b -> a     -- Defined in ‘GHC.Real’
18 infixr 8 ^
View Code

  2.5 变量的定义

使用ghci的let定义临时变量

Real World Haskell学习篇-第1章: 入门Real World Haskell学习篇-第1章: 入门
1 ghci>>> pi
2 3.141592653589793
3 ghci>>> e
4 
5 <interactive>:84:1: Not in scope: ‘e’
6 ghci>>> let e = exp 1
7 ghci>>> e
8 2.718281828459045
View Code

exp 1 表示调用指数函数exp,参数为1, 不必使用()。

3. 列表(List)

  列表长度可以是任意的。

  空的列表就是[]。

  列表中的元素必须相同类型。

Real World Haskell学习篇-第1章: 入门Real World Haskell学习篇-第1章: 入门
 1 ghci>>> [1,2,3,4]
 2 [1,2,3,4]
 3 ghci>>> []
 4 []
 5 ghci>>> ['foo','rt']
 6 
 7 <interactive>:89:2:
 8     Syntax error on 'foo'
 9     Perhaps you intended to use TemplateHaskell
10     In the Template Haskell quotation 'foo'
11 ghci>>> ["foo","rt"]
12 ["foo","rt"]
13 ghci>>> [True,False,1,"str"]
14 
15 <interactive>:91:15:
16     Couldn't match expected type ‘Bool’ with actual type ‘[Char]’
17     In the expression: "str"
18     In the expression: [True, False, 1, "str"]
19     In an equation for ‘it’: it = [True, False, 1, ....]
View Code

  可以用列举符号 .. 表示一系列的列表元素, 也可以根据前面的元素步长,自动填充后面省略的元素, 但是float类型可能会涉及到四舍五入的情况:

Real World Haskell学习篇-第1章: 入门Real World Haskell学习篇-第1章: 入门
 1 ghci>>> [1..10]
 2 [1,2,3,4,5,6,7,8,9,10]
 3 ghci>>> [1,4,7..20]
 4 
 5 <interactive>:93:7: parse error on input ‘..’
 6 ghci>>> [1,4,7,..20]
 7 
 8 <interactive>:94:8: parse error on input ‘..’
 9 ghci>>> [1,4..20]
10 [1,4,7,10,13,16,19]
11 ghci>>> [1,8..20]
12 [1,8,15]
13 ghci>>> [1.2..2.3]
14 [1.2,2.2]
15 ghci>>> [1.2..2.6]
16 [1.2,2.2]
17 ghci>>> [1.2..3.6]
18 [1.2,2.2,3.2]
19 ghci>>> [1.0..1.8]
20 [1.0,2.0]
View Code

  当然你可以用[1..], 省略终点的方式产生一个无穷数列。

3.1 列表操作符 (连接)

  使用 ++ 连接N个相同元素的列表。

  使用 : 在某列表头部加入。(格式必须: 前面是单个元素,后面是一个列表)

Real World Haskell学习篇-第1章: 入门Real World Haskell学习篇-第1章: 入门
 1 ghci>>> [] ++ [False,True] ++ [False]
 2 [False,True,False]
 3 ghci>>> 100:[2,3,4,5] ++ [6,8,4]
 4 [100,2,3,4,5,6,8,4]
 5 ghci>>> [2,3]:1
 6 
 7 <interactive>:105:1:
 8     Non type-variable argument in the constraint: Num [[t]]
 9     (Use FlexibleContexts to permit this)
10     When checking that ‘it’ has the inferred type
11       it :: forall t. (Num t, Num [[t]]) => [[t]]
View Code

4. 字符串和字符

  字符串就是很多个单字符组成的列表, 所以可以列表的连接操作。

  putStrLn 是输出字符串的函数。 \n \r 与C语言一样转意。

  ""与[]是相同的。

Real World Haskell学习篇-第1章: 入门Real World Haskell学习篇-第1章: 入门
 1 ghci>>> "Hello Haskell"
 2 "Hello Haskell"
 3 ghci>>> putStrLn "We are in ghci console.\n See here."
 4 We are in ghci console.
 5  See here.
 6 ghci>>> 'c'
 7 'c'
 8 ghci>>> let a = ['h','e','l','l','o']
 9 ghci>>> a
10 "hello"
11 ghci>>> a == "hello"
12 True
13 ghci>>> [] == ""
14 True
15 ghci>>> 'w':"Haskell"
16 "wHaskell"
17 ghci>>> "Frist" ++ "Second"
18 "FristSecond"
View Code

5. 类型表示

  Haskell中,所有的类型以大写字母开始,变量以小写字母开始。

  可以使用 :set +t 是ghci返回结果的类型, :unset +t。

  可以使用 :type var/expression 显示变量或表达式的类型, 并不参与计算。

Real World Haskell学习篇-第1章: 入门Real World Haskell学习篇-第1章: 入门
 1 ghci>>> :set +t
 2 ghci>>> 'c'
 3 'c'
 4 it :: Char
 5 ghci>>> "foo"
 6 "foo"
 7 it :: [Char]
 8 ghci>>> 7^80
 9 40536215597144386832065866109016673800875222251012083746192454448001
10 it :: Num a => a
11 ghci>>> :m +Data.Ratio
12 ghci>>> 11 % 33
13 1 % 3
14 it :: Integral a => Ratio a
15 ghci>>> 11 % 3.3
16 
17 <interactive>:121:1:
18     No instance for (Fractional a0) arising from a use of ‘it’
19     The type variable ‘a0’ is ambiguous
20     Note: there are several potential instances:
21       instance Integral a => Fractional (Ratio a)
22         -- Defined in ‘GHC.Real’
23       instance Fractional Double -- Defined in ‘GHC.Float’
24       instance Fractional Float -- Defined in ‘GHC.Float’
25     In the first argument of ‘print’, namely ‘it’
26     In a stmt of an interactive GHCi command: print it
27 ghci>>> :unset +t
28 ghci>>> type 'c'
29 
30 <interactive>:123:6: parse error on input ‘'
31 ghci>>> :type 'c'
32 'c' :: Char
33 ghci>>> :type 1+8
34 1+8 :: Num a => a
View Code

6. 行计数程序 (WC.hs)

 1 main = interact wordCount 2 where wordCount input = show (length (lines input)) ++ "\n" 

然后新建一个quux.txt文件进行测试(内容随便写写)。

打开shell命令行切换到当前目录, 执行: runghc WC < quux.txt

即可得到txt文件的行数。