Haskell: Funktional
Programming
安装 Haskell
进入这个网站
然后在终端运行他们的安装脚本
1 curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
出现提示后就根据提示输入 YES
然后回车就好了
然后退出终端重新进入后,就可以了
在vscode中可以搜索安装 Haskell 插件
安装 stack
的 hlint
即可, 如果
stack
安装不了,可以更新一下系统再安装
1 2 sudo pacman -S stack stack install hlint
安装package
比如安装 QuickCheck, 因为它是 library 所以加上 --lib
1 cabal install --lib QuickCheck
Haskell 基本语法
Haskell 网上教程
https://www.bookstack.cn/read/learnyouahaskell-zh-tw/README.md
Hello World
新建一个 hello.hs
文件
1 2 main :: IO ()main = putStrLn "hello, world"
编译命令
一键编译运行的时候可以使用
在终端输入 ghci
可以进入交互界面
基本语句
stack ghci //运行haskell在命令行
1 2 3 4 5 6 7 :type True "Hello" ++ "World" 123 :: Float ['H' ,'e','l','l','o'] length "Hello" let a = undefined :t (==)
函数
定义函数 \(f:A\times B \rightarrow
C\)
调用函数 \(f(a), f(a,b), f(g(b)), f(a,
g(b))\)
1 2 3 4 f af a b f (g b)f a (g b)
优先级
布尔运算
这些是定义好的,最后一个是不等于
1 True False not && || == /=
数据类型
Bool
Integer
Char
String
Tuple
QuickCheck
首先安装好 QuickCheck, 上文有提到, 然后import一下
我们这里定义2个函数
1 2 xor2 :: Bool -> Bool -> Bool xor2 x y = (x || y) && not(x && y)
下面这个是用 pattern matching 的方式定义的
1 2 3 4 5 xor :: Bool -> Bool -> Bool xor True True = False xor True False = True xor False True = True xor False False = False
然后在 main
里面写
1 2 main = do quickCheck prop_xor2
就可以测试了
Integer
大整数类型
运算符有
1 + - * ^ div mod abs == /= < <= > >=
Int
是至少 29bit 的整数类型
输出语句
1 2 print 3 putStrLn "hello"
函数里面的分支
1 2 3 4 max2 :: Integer -> Integer -> Integer max2 x y| x >= y = x | otherwise = y
或者写在行内
1 max2 x y = if x >= y then x else y
List
list 类型是在外面加一个方括号
如 [Int]
1 [1 .. 5 ] = [1 , 2 , 3 , 4 , 5 ]
列表相加
只能相同类型的
1 [1 , 2 ] ++ [3 ] = [1 , 2 , 3 ]
List Comprehension
Generators
\[
\left\{x^{2} \mid x \in\{1,2,3,4,5\}\right\}
\]
1 2 3 [x^2 | x <- [1 .. 5 ]] [(x, even x) | x <- [1 .. 3 ]] [x+y | (x, y) <- [(1 , 2 ), (3 , 4 ), (5 , 6 )]]
多重生成器
1 2 3 4 5 6 7 [(i,j) | i <- [1 .. 2 ], j <- [7 .. 9 ]] [(i,j) | i <- [1 .. 3 ], j <- [i .. 3 ]] = [(1 ,j) | j <- [1 ..3 ]] ++ [(2 ,j) | j <- [2 ..3 ]] ++ [(3 ,j) | j <- [3 ..3 ]] = [(1 ,1 ), (1 ,2 ), (1 ,3 ), (2 ,2 ), (2 ,3 ), (3 ,3 )]
Tests
1 2 [x*x | x <- [1 .. 5 ], odd x] = [1 , 9 , 25 ]
concat
1 2 3 4 5 concat [[1 ,2 ], [4 ,5 ,6 ]]= [x | xs <- [[1 ,2 ], [4 ,5 ,6 ]], x <- xs] = [x | x <- [1 ,2 ]] ++ [x | x <- [4 ,5 ,6 ]] = [1 ,2 ] ++ [4 ,5 ,6 ] = [1 ,2 ,4 ,5 ,6 ]
抽象函数
下面 a
是一个类型变量
https://blog.csdn.net/zwvista/article/details/61454004
1 2 3 4 5 6 7 8 9 10 id :: a -> aid x = xfst :: (a,b) -> afst (x,y) = xswap :: (a,b) -> (b,a)swap (x,y) = (y,x)silly :: Bool -> a -> Char silly x y = if x then ’c’ else ’d’silly2 :: Bool -> Bool -> Bool silly2 x y = if x then x else y
Num
是一个数字类型,比如 Int,Integer,Float
也是
证明
cyp
.cprf
证明文件
.cthy
定理文件
运行证明
先进入cyp的根目录,然后运行下面的命令
1 stack run cyp [.cthy] [.cprf]
一般证明
1 2 3 4 5 6 Lemma sndUnspliceNil: snd (unsplice []) .=. [] Proof snd (unsplice []) (by def unsplice) .=. snd (Pair [] []) (by def snd) .=. [] QED
Proof by Induction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Lemma appNil: xs ++ [] .=. xs Proof by induction on List xs Case [] To show: [] ++ [] .=. [] Proof [] ++ [] (by def ++) .=. [] QED Case (x:xs) To show: (x:xs) ++ [] .=. (x:xs) IH: xs ++ [] .=. xs Proof (x:xs) ++ [] (by def ++) .=. x : (xs ++ []) (by IH) .=. x : xs QED QED
Proof by Cases
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Lemma fstUnspliceF: fst (unsplice xs') .=. drop2 xs' Proof by case analysis on List xs' Case [] Assumption : xs' .=. [] Proof fst (unsplice xs') (by Assumption) .=. fst (unsplice []) (by fstUnspliceNil) .=. [] (by def drop2) .=. drop2 [] (by Assumption) .=. drop2 xs' QED Case x:xs Assumption : xs' .=. x:xs Proof fst (unsplice xs') (by Assumption) .=. fst (unsplice (x:xs)) (by fstUnsplice) .=. drop2 (x:xs) (by Assumption) .=. drop2 xs' QED QED
Proof by computation
induction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 Lemma spliceDrop2: splice (drop2 (x : xs)) (drop2 xs) .=. x : xs Proof by computation induction on xs with drop2 Case 1 To show: splice (drop2 [x]) (drop2 []) .=. [x] Proof splice (drop2 [x]) (drop2 []) (by def drop2) .=. splice [x] (drop2 []) (by def drop2) .=. splice [x] [] (by def splice) .=. x : splice [] [] (by def splice) .=. [x] QED Case 2 To show: splice (drop2 [x, y]) (drop2 [y]) .=. [x, y] Proof splice (drop2 [x, y]) (drop2 [y]) (by def drop2) .=. splice (drop2 [x, y]) [y] (by def drop2) .=. splice (x : drop2 []) [y] (by def drop2) .=. splice [x] [y] (by def splice) .=. x : splice [y] [] (by def splice) .=. x : y : splice [] [] (by def splice) .=. [x, y] QED Case 3 To show: splice (drop2 (x : y : z : xs)) (drop2 (y : z : xs)) .=. x : y : z : xs IH: splice (drop2 (x : xs)) (drop2 xs) .=. x : xs Proof splice (drop2 (x : y : z : xs)) (drop2 (y : z : xs)) (by def drop2) .=. splice (x : drop2 (z : xs)) (drop2 (y : z : xs)) (by def drop2) .=. splice (x : drop2 (z : xs)) (y : drop2 xs) (by def splice) .=. x : splice (y : drop2 xs) (drop2 (z : xs)) (by def splice) .=. x : y : splice (drop2 (z : xs)) (drop2 xs) (by IH) .=. x : y : z : xs QED QED
map
把一个函数映射到所以元素
1 2 map even [1 , 2 , 3 ]= [False , True , False ]
lambda 表达式
Type Classes
定义具体类
1 2 3 4 5 instance Eq a => Eq [a] where [] == [] = True (x:xs) == (y:ys) = x == y && xs == ys _ == _ = False
定义约束条件
1 2 3 4 5 6 7 8 9 10 11 class Size a where size :: a -> Float data Shape = Square Float | Circle Float instance Size Shape where size (Square a) = a*a size (Circle a) = a*a*pi instance Size a => Size [a] where size xs = sum (map size xs)
IO
IO Char:
返回一个Char类型的动作
IO ():
没有返回的动作
基础动作
1 2 3 getChar :: IO Char putChar :: Char -> IO ()return :: a -> IO a
do 来连接
1 2 3 4 5 get2 :: IO (Char ,Char )get2 = do x <- getChar getChar y <- getChar return (x,y)
strlen
1 2 3 4 5 6 7 strLen :: IO ()strLen = do putStr "Enter a string: " xs <- getLineputStr "The string has " putStr (show (length xs))putStrLn " characters"
读入int
1 2 3 4 5 6 7 8 readNum :: IO Integer readNum = do x <- readLn if 1 <= x && x <= 5 then return x else do putStrLn "Eingabe muss zwischen 1 und 5 liegen ." readNum
putStrLn
连接变量
1 2 putStrLn $ " Streichhoelzer : " ++ show a ++ ". Spieler " ++ show s ++ "?"
递归例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ioSeq :: [IO a] -> IO [a]ioSeq [] = return []ioSeq (x:xs) = do y <- x ys <- ioSeq xs return (y : ys) getio :: String -> IO String getio s = do putStrLn $ s ++ "?" getLine fillForm :: [String ] -> IO [String ]fillForm xs = ioSeq [getio x | x <- xs]
文件IO
Modules and Abstract Data
Types
Lazy evaluation