Programming in Haskell是一本入门Haskell的好书,介绍页面以及配套的slides, vedios, codes都在这里。
用map
和filter
表示[f x | x <- xs, p x]
定义高阶函数all
, any
, takeWhile
, dropWhile
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 38 39 40 41 42 43 44 45
| myall :: (a -> Bool) -> [a] -> Bool myall _ [] = True myall p (x : xs) | p x == False = False | otherwise = myall p xs
myany :: (a -> Bool) -> [a] -> Bool myany _ [] = False myany p (x : xs) | p x == True = True | otherwise = myany p xs
mytakeWhile :: (a -> Bool) -> [a] -> [a] mytakeWhile _ [] = [] mytakeWhile p (x : xs) | p x == True = x : mytakeWhile p xs | otherwise = []
mydropWhile :: (a -> Bool) -> [a] -> [a] mydropWhile _ [] = [] mydropWhile p (x : xs) | p x == True = mydropWhile p xs | otherwise = x : xs
|
用foldr
定义map f
和filter p
1 2 3 4 5 6
| mymap f = foldr (\x xs -> f x : xs) []
myfilter p = foldr (\x xs -> if p x then x : xs else xs) []
|
用foldl
定义dec2int :: [Int] -> Int
1 2 3 4 5 6 7 8 9
| dec2int :: [Int] -> Int dec2int = foldl (\x y -> x * 10 + y) 0
|
修改错误:sumsqreven = compose [sum, map (^2), filter even]
1 2 3 4
| compose = foldr (.) id
sumsqreven xs = sum (compose [map (^2), filter even] xs)
|
curry
& uncurry
1 2 3 4 5 6 7 8 9
|
mycurry :: ((a, b) -> c) -> (a -> b -> c) mycurry f = \x y -> f (x, y)
myuncurry :: (a -> b -> c) -> ((a, b) -> c) myuncurry f = \(x, y) -> f x y
|
利用unfold
定义chop8
, map f
, iterate f
1 2 3 4 5 6 7 8 9 10 11
| unfold p h t x | p x = [] | otherwise = h x : unfold p h t (t x)
int2bin' = unfold (== 0) (`mod` 2) (`div` 2)
chop8' :: [Int] -> [[Int]] chop8' = unfold (== []) (take 8) (drop 8)
mymap' f = unfold (== []) (f.head) tail
myiterate f = unfold (\_ -> False) id f
|
给string transmitter程序加上奇偶校验位(parity bit)
我这里是在数据位的末端添加的,奇数个1则为1,否则为0。
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
type Bit = Int
bin2int :: [Bit] -> Int
bin2int = foldr (\x y -> x + 2 * y) 0
int2bin :: Int -> [Bit] int2bin 0 = [] int2bin n = n `mod` 2 : int2bin (n `div` 2)
make8 :: [Bit] -> [Bit] make8 bits = take 8 (bits ++ repeat 0)
count1 :: [Bit] -> Bit count1 = (`mod` 2) . sum
addparitybits :: [Bit] -> [Bit] addparitybits bits = bits ++ [count1 bits]
encode :: String -> [Bit] encode = concat.map (addparitybits.make8.int2bin.ord)
chop9 :: [Bit] -> [[Bit]] chop9 [] = [] chop9 bits = take 9 bits : chop9 (drop 9 bits)
isvalid :: [Bit] -> Bool isvalid bits = (count1 (take 8 bits)) == (last bits)
decode :: [Bit] -> String
decode xs | all isvalid (chop9 xs) = map (chr.bin2int.(take 8)) (chop9 xs) | otherwise = error "Wrong parity bit!"
transmit :: String -> String transmit = decode.channel.encode
channel :: [Bit] -> [Bit] channel = id
transmit' :: String -> String transmit' = decode.tail.encode
|