Haskell 编程学习笔记

1. 变量与常量

Haskell 中的变量一旦定义即不可变,因此变量更像常量。定义变量使用 = 赋值。

name = "Alice"
age = 30

注意事项:Haskell 是懒惰求值的,变量的值在需要时才会被计算。

2. 数据类型

Haskell 是强类型语言,常用的数据类型有 IntFloatCharBool

height :: Float
height = 1.75

isStudent :: Bool
isStudent = True

易错点:确保变量类型与值类型一致,Haskell 编译器会检查类型一致性。

3. 条件表达式

Haskell 中的条件表达式使用 ifthenelse 关键字。

status = if age > 18 then "Adult" else "Minor"

注意事项: if 表达式必须有 else 分支。

4. 函数

使用 letwhere 关键字定义局部函数。

greet :: String -> String
greet name = "Hello, " ++ name

注意事项:Haskell 函数是纯函数,不会改变外部状态。

5. 递归

递归是 Haskell 处理循环的一种方式。

factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n - 1)

易错点:确保递归有基准情况,否则会导致无限递归。

6. 数据结构

Haskell 支持列表、元组等数据结构,列表用 [] 定义。

names = ["Alice", "Bob", "Charlie"]
pair = (1, "one")

注意事项:列表元素必须是相同类型,元组可以包含不同类型。

7. 类型类

Haskell 中的类型类类似接口,EqShow 是常见的类型类。

data Person = Person { name :: String, age :: Int } deriving (Show, Eq)

注意事项: deriving 关键字自动实现常用类型类。

8. 模式匹配

模式匹配是 Haskell 中非常有用的功能,用于检查和解构数据结构。

describe :: Int -> String
describe 1 = "One"
describe 2 = "Two"
describe _ = "Other"

易错点:使用 _ 作为通配符匹配所有其他情况,避免遗漏。

9. 惰性求值

Haskell 默认是惰性求值,表达式仅在需要时计算。

infiniteList = [1..]  -- 无限列表

注意事项:使用惰性求值时需谨慎,避免无穷计算。

10. Monad

Monad 是 Haskell 中的一种抽象概念,常用于处理输入输出和错误。

greet :: IO ()
greet = do
    putStrLn "Enter your name:"
    name <- getLine
    putStrLn ("Hello, " ++ name)

注意事项:IO 操作需在 Monad 中使用,避免副作用。

高级与小众用法

列表解析

Haskell 支持列表解析语法,生成新的列表。

squares = [x^2 | x <- [1..10]]

注意事项:确保列表生成条件合理,以避免性能问题。

高阶函数

Haskell 支持将函数作为参数传递或返回。

applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)

易错点:高阶函数的类型签名应明确参数和返回值类型。

部分应用

Haskell 支持函数的部分应用,通过传入部分参数生成新函数。

addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z

addTwo = addThree 5 3  -- 部分应用

注意事项:部分应用适合简化多参数函数,但参数过多时应考虑代码可读性。

自定义类型和别名

使用 type 为已有类型创建别名,data 定义新类型。

type Age = Int
data Person = Person String Age

易错点:避免类型名称与函数名重复。

函数组合

Haskell 使用 . 运算符进行函数组合。

compose :: (b -> c) -> (a -> b) -> a -> c
compose f g x = f (g x)

注意事项:组合时确保函数的参数和返回值类型匹配。

Guard 表达式

Guard 表达式类似于条件判断,用于选择不同的分支。

factorial :: Int -> Int
factorial n
    | n <= 1    = 1
    | otherwise = n * factorial (n - 1)

注意事项:使用 | 定义多个条件分支,otherwise 表示默认分支。