[ (a, b) | a <- [1..2], b <- [1..3] ] -- [(1,1),(1,2),(1,3),(2,1),(2,2),(2,3)]
过滤:x > 1,所有的过滤条件都为True值才会出现在结果中
1
l = [ x | let xs = [1,2,3], x <- xs, x > 1 ]
取值时是从左到右的:
1 2 3
[ x | let xs = [1,2,3], let xs = [1,2,3,4], x <- xs, x > 1 ] -- [2,3,4][ x | let xs = [1,2,3], x <- xs, let xs = [], x > 1 ] -- [2,3][ x*2 | False, x <- [1,2] ] -- []
flip' :: (a -> b -> c) -> b -> a -> c-- flip' f 替换为g,然后将 g x y 替换为 f y xflip' f = gwhere g x y = f y x-- 更简单的方法flip' :: (a -> b -> c) -> b -> a -> c-- 命题:flip' f x y 的值等于 f y x 的值flip' f x y = f y x
f :: Int -> Intf 0 = 1f n | n == 1 = 1 | n <= 10 = f (n-1) * n | otherwise = error ("n to big: " ++ (show n))
where
where定义的量(可以定义名字和函数)只在本模式内可见,并且通过换行或分号分隔
如果有guard,where必须在本模式所有的guard后面
1 2 3 4 5 6 7 8 9 10 11 12 13
bmiTell :: (RealFloata) => a -> a -> StringbmiTell weight height | bmi <= skinny = "You're underweight, you emo, you!" | bmi <= normal = "You're supposedly normal. Pffft, I bet you're ugly!" | bmi <= fat = "You're fat! Lose some weight, fatty!" | otherwise = "You're a whale, congratulations!"where bmi = weight / height ^ 2 skinny = 18.5 normal = 25.0 fat = 30.0 或者where bmi = weight / height ^ 2 (skinny, normal, fat) = (18.5, 25.0, 30.0)
let
有两种形式:
第一种,它是一个表达式,任何能使用表达式的地方都能使用:
1 2 3 4
-- 每个部分必须存在let <bindings> in <expression><bindings>: <binding>[(;|回车)<binding>]*<binding>: <name> = <value>
let在<bindings>定义的量只在当前let表达式内可见
let表达式的值是<expression>的值
在函数中使用可以通过换行来分隔binding,此时;可写可不写
第二种,没有in部分,用在do和列表生成式中,用来定义do和列表生成式中的局部的量:
1
let <bindings>
如果在ghci命令行中输入,不加in <expression>不是let表达式,相当于在外围定义量
case 表达式
1
case <exp> of (<pattern> -> <exp'>)+
将<exp>的值从上到下进行<pattern>的匹配,匹配成功后返回<exp'>的值
1 2 3 4 5 6 7 8
head' :: [a] -> ahead' [] = error "Can't call head on an empty list, dummy!"head' (x:_) = x-- 可以用分号或者换行分隔head' xs = case xs of[] -> error "Can't call head on an empty list, dummy!" (x:_) -> x
可以使用do notation将许多I/O action打包,最后一个函数的返回值就是整体的返回值,可以使用return函数包装返回值(Monad m => a -> m a,IO就是一个Monad,它只是个函数不会终止调用它的函数)
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
main = do putStrLn "please enter an number:" run 33run x = do number <- getLineif null numberthen return ()elsedo-- 必须用do打包成一个整体let num = read number :: Intif num == xthen putStrLn "correct!"elsedoif num < xthen putStrLn "less"else putStrLn "greater" run x
函数
putChar、putStr、putStrLn、print(putStrLn . show)
getChar(Enter 被按下的时候才会触发读取字符的行为,回车也会被获取到)
getLine
do
do notation 是一个语法糖,具体请看:Haskell类型.md 的 Monad 部分
1 2 3 4 5 6 7 8 9 10 11
main = do putStrLn "What is your name?" a <- getLine putStrLn "How old are you?" b <- getLine print (a,b)# 解语法糖后:main = putStrLn "What is your name?" >> getLine >>= \a -> putStrLn "How old are you?" >> getLine >>= \b -> print (a,b)