halve :: Int -> Int halve x = x / 2 error: • Noinstance for (FractionalInt) arising from a use of ‘/' • In the expression: x / 2 In an equation for ‘halve': halve x = x / 2 ghci> div 72 3 ghci> 7.0 / 2.0 3.5
因为 / 表示小数除法,div 表示整除
/= 表示“不等于”
在 Haskell 中,没有语句 statement,它的 if 是表达式 expression,必须有 else
price = if product == "milk"then1else2
定义
where 把本地定义加到定义中
circleArea :: Double -> Double circleArea r = pi * square r where pi = 3.1415926 square x = x * x
let...in 是一个表达式
circleArea r = let pi = 3.1415926 square x = x * x in pi * square r
变量定义后是不可变 immutable 的,所以其本质上是一个定义 definition
本地定义会屏蔽 shadow 外部同名定义
模式匹配
按照顺序匹配直到找到对应的
greet :: String -> String -> String greet"Finland" name = "Hei, " ++ name greet"Italy" name = "Ciao, " ++ name greet"England" name = "How do you do, " ++ name greet _ name = "Hello, " ++ name
_ 表示匹配所有东西,也可以用一个定义 s 代替
循环
用尾递归代替
factorial :: Int -> Int factorial1 = 1 factorial n = n * factorial (n-1)
缩进
总的来说是:
一组的东西从同一列开始
如果表达式不得不分到不同行,则增加缩进
i x = let y = x+x+x+x+x+x in div y 5
j x = let y = x+x+x +x+x+x in div y 5
k = a + b where a = 1 b = 1
l = a + b where a = 1 b = 1
要么作为英雄而死… Either You Die a Hero…
Either you die a hero, or you live long enough to see yourself become the villain.
要么像英雄一般死去,要么看着自己变成恶棍。
——《蝙蝠侠·黑暗骑士》
我不知道这个标题是什么意思
递归与帮手函数
通常在原函数后加 ‘ 表示帮手函数
fibonacci :: Integer -> Integer fibonacci n = fibonacci' 01 n
fibonacci' :: Integer -> Integer -> Integer -> Integer fibonacci' a b 1 = b fibonacci' a b n = fibonacci' b (a+b) (n-1)
警卫(多分支)
f x y z | 条件 1 = something | 条件 2 = other | otherwise = somethingother
-- 构造列表 descend0 = [] descend n = n : descend (n-1)
列表可应用模式匹配
describeList :: [Int] -> String describeList [] = "an empty list" describeList (x:[]) = "a list with one element" describeList (x:y:[]) = "a list with two elements" describeList (x:y:z:xs) = "a list with at least three elements"
map 和 filter 的实现:
map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = f x : map f xs
filter :: (a -> Bool) -> [a] -> [a] filter _pred [] = [] filter pred (x:xs) | pred x = x : filter pred xs | otherwise = filter pred xs
(==) :: (Eq a) => a -> a -> Bool (/=) :: Eq a => a -> a -> Bool
类型约束:
f :: (Eq a) => (a -> a) -> a -> Bool f g x = x == g x
其他标准类型类:
Ord 类表示支持排序的类型,Ordering 类型的值 LT 表示小于,RT 表示大于,EQ 表示等于,支持 sort 等
compare :: Ord a => a -> a -> Ordering (<) :: Ord a => a -> a -> Bool (>) :: Ord a => a -> a -> Bool (>=) :: Ord a => a -> a -> Bool (<=) :: Ord a => a -> a -> Bool max :: Ord a => a -> a -> a min :: Ord a => a -> a -> a
Num 包括整数算术
(+) :: Num a => a -> a -> a (-) :: Num a => a -> a -> a (*) :: Num a => a -> a -> a negate :: Num a => a -> a -- 0-x abs :: Num a => a -> a -- absolute value signum :: Num a => a -> a -- -1 for negative values, 0 for 0, +1 for positive values fromInteger :: Num a => Integer -> a
Integral 表示整数,包括 Int 和 Integer,该类型属于 Num
div :: Integral a => a -> a -> a mod :: Integral a => a -> a -> a
Fractional 是支持除法的类,属于 Num
(/) :: Fractional a => a -> a -> a
Floating 属于 Num,支持一些只有浮点数才支持的操作
sqrt :: Floating a => a -> a sin :: Floating a => a -> a
Read 和 Show 类支持把字符串转为值和把值转字符串
show :: Show a => a -> String read :: Read a => String -> a
Foldable 表示可以 foldr 的类
数据结构
Data.Map 类似于 [(k, v)],但支持更多操作
引入:
importqualified Data.Map as Map
支持的函数:
-- 从列表中创建键-值对 Map.fromList :: Ord k => [(k, a)] -> Map.Map k a
-- 向 map 中插入一对键值对,会覆盖原有的 -- 返回一个新的 map,不会修改原来的 Map.insert :: Ord k => k -> a -> Map.Map k a -> Map.Map k a
-- 使用一个键返回值,如果没有,返回 Nothing Map.lookup :: Ord k => k -> Map.Map k a -> Maybe a
-- 空 map Map.empty :: Map.Map k a
Data.Array 有点不同,是一个二元类
构造方法:
array :: Ix i => (i, i) -> [(i, e)] -> Array i e listArray :: Ix i => (i, i) -> [e] -> Array i e -- 从列表创建,更简单
操作:
-- Array 查找 (!) :: Ix i => Array i e -> i -> e -- Array 更新,注意一次可以更新多个 (//) :: Ix i => Array i e -> [(i, e)] -> Array i e
GHCi> :t getLine getLine :: IOString GHCi> line <- getLine another line GHCi> :t line line :: String GHCi> line "another line" GHCi> reverse line "enil rehtona"