haskell模块


In [ ]:
-- 一般包含函数/类型/类型类, 允许到处部分定义
-- prelude为自动导入模块,

In [1]:
-- import必须放到函数定义前
-- import回直接食用全局命名空间
-- 使用hoogle查询文档

In [2]:
-- ghci中使用 :m + 导入模块

In [3]:
:m + Data.List

In [5]:
-- 一次import多个
:m + Data.List Data.Map Data.Set

In [6]:
-- 部分导入
import Data.List (nub, sort)

In [7]:
-- import hide
import Data.List hiding (nub)

In [9]:
-- 限定导入, 需要使用前缀访问
import qualified Data.Map

In [10]:
-- 限定导入别名
import qualified Data.Map as M

使用prelude模块


In [12]:
words "hey these are the words in the sentence"


["hey","these","are","the","words","in","the","sentence"]

In [13]:
words "hey these    are the words in this sentence"


["hey","these","are","the","words","in","this","sentence"]

In [14]:
group [1,1,1,1, 2,2,2,2,2,2, 3,3]


[[1,1,1,1],[2,2,2,2,2,2],[3,3]]

In [15]:
group ["boom", "bip", "bip", "boom", "boom"]


[["boom"],["bip","bip"],["boom","boom"]]

In [16]:
sort [5,4,3,7,2,1]


[1,2,3,4,5,7]

In [19]:
sort ["boom", "bip", "bip", "boom", "boom"]


["bip","bip","boom","boom","boom"]

In [3]:
import Data.List
wordNums :: String -> [(String, Int)]
wordNums = map (\ws -> (head ws, length ws)) . group . sort . words

In [2]:
-- use this to unload import module
:m -Data.Set -Data.Map

In [4]:
import Data.List
wordNums xs = map (\ws -> (head ws, length ws)) . group . sort . words


Use &&&
Found:
\ ws -> (head ws, length ws)
Why Not:
head Control.Arrow.&&& length

In [7]:
:t wordNums


wordNums :: forall t. t -> String -> [(String, Int)]

In [8]:
wordNums xs = map (\ws -> (head ws, length ws)) . group . sort . words


Use &&&
Found:
\ ws -> (head ws, length ws)
Why Not:
head Control.Arrow.&&& length

In [9]:
"hawaii" `isPrefixOf` "hawaii joe"


True

In [10]:
"haha" `isPrefixOf` "ha"


False

In [11]:
"ha" `isPrefixOf` "ha"


True

In [12]:
any (> 4) [1, 2, 3]


False

In [13]:
any (=='F') "Frank Sobotka"


Use elem
Found:
any (== 'F')
Why Not:
elem 'F'
True

In [14]:
any (\x -> x > 5 && x < 10) [1, 4, 11]


False

In [15]:
import Data.List

In [18]:
isIn :: (Eq a) => [a] -> [a] -> Bool
needle `isIn` haystack = any (needle `isPrefixOf`) (tails haystack)

In [19]:
"art" `isIn` "party"


True

In [20]:
[1, 2] `isIn` [1, 2, 3]


True

In [22]:
import Data.Char
ord 'a'


97

In [23]:
chr 97


'a'

In [24]:
map ord "abcdefgh"


[97,98,99,100,101,102,103,104]

In [25]:
import Data.Char
encode :: Int -> String -> String
encode offset msg = map (\c -> chr $ ord c + offset) msg

In [26]:
encode 3 "hey mark"


"kh|#pdun"

In [28]:
encode 5 "please instruct your men"


"uqjfxj%nsxywzhy%~tzw%rjs"

In [29]:
encode 1 "to party hard"


"up!qbsuz!ibse"

In [30]:
decode :: Int -> String -> String
decode shift msg = encode (negate shift) msg

In [31]:
decode 3 "kh|#pdun"


"hey mark"

In [32]:
decode 5 "uqjfxj%nsxywzhy%~tzw%rjs"


"please instruct your men"

In [33]:
decode 1 "up!qbsuz!ibse"


"to party hard"

In [34]:
-- 严格左折叠
-- foldl会延时计算,遇到大list时会溢出。可以使用Data.List里的fold1(非延时计算)

In [35]:
foldl (+) 0 (replicate 100 1)


Use sum
Found:
foldl (+) 0
Why Not:
sum
100

In [37]:
-- why not fails????
foldl (+) 0 (replicate 10000000 1)


Use sum
Found:
foldl (+) 0
Why Not:
sum
10000000

In [39]:
foldl' (+) 0 (replicate 10000000 1)


10000000

In [40]:
-- 寻找酷数
digitToInt '2'


2

In [41]:
digitToInt 'F'


15

In [43]:
-- this would raise
digitToInt 'z'


Char.digitToInt: not a digit 'z'

In [44]:
import Data.Char
import Data.List

digitSUm :: Int -> Int
digitSUm = sum . map digitToInt . show

In [46]:
-- Data.List find 找list中第一个满足条件的元素
:t find


find :: forall a (t :: * -> *). Foldable t => (a -> Bool) -> t a -> Maybe a

In [48]:
-- 使用maybe表示可能失败的计算, Nothing表示空, Just
Nothing


Nothing

In [49]:
Just "Hey"


Just "Hey"

In [50]:
Just 3


Just 3

In [51]:
:t Just "hey"


Just "hey" :: Maybe [Char]

In [52]:
:t Just True


Just True :: Maybe Bool

In [53]:
find (> 4) [3, 4, 5, 6, 7]


Just 5

In [54]:
find odd [2, 4, 6, 8, 9]


Just 9

In [55]:
find (=='z') "mjolnir"


Nothing

In [57]:
firstTo40 :: Maybe Int
firstTo40 = find (\x -> digitSUm x == 40) [1..]

In [58]:
firstTo40


Just 49999

In [62]:
firstTo :: Int -> Maybe Int
firstTo n = find (\x -> digitSUm x == n) [1..]

In [63]:
firstTo 40


Just 49999

In [64]:
firstTo 1


Just 1

In [65]:
firstTo 13


Just 49

In [66]:
-- 关联列表, 映射map
playBook = [("betty", "555"), ("bonnie", "452"), ("patsy", "493")]

In [68]:
findKey :: (Eq k) => k -> [(k, v)] -> v
findKey key xs = snd . head . filter (\(k, v) -> key == k) $ xs

In [71]:
-- not raise while empty list
findKey :: (Eq k) => k -> [(k, v)] -> Maybe v
findKey key [] = Nothing
findKey key ((k, v):xs)
    | key == k = Just v
    | otherwise = findKey key xs

In [72]:
-- fold version
findKey :: (Eq k) => k -> [(k, v)] -> Maybe v
findKey key xs = foldr (\(k,v) acc -> if key == k then Just v else acc) Nothing xs

In [75]:
findKey "penny" playBook


Nothing

In [76]:
findKey "betty" playBook


Just "555"

In [77]:
findKey "wilma" playBook


Nothing

In [78]:
-- Data.Map实现了Map
import qualified Data.Map as Map

In [81]:
Map.fromList [(3, "shoes"), (4, "trees"), (9, "bees")]


fromList [(3,"shoes"),(4,"trees"),(9,"bees")]

In [82]:
Map.fromList [("jay", "landsman"), ("jummy", "mcnulty"), ("kima", "greggs")]


fromList [("jay","landsman"),("jummy","mcnulty"),("kima","greggs")]

In [83]:
-- key重复,旧值被忽略
Map.fromList [("MS", 1), ("MS", 2), ("MS", 3)]


fromList [("MS",3)]

In [84]:
:t  Map.fromList


Map.fromList :: forall k a. Ord k => [(k, a)] -> Map k a

In [86]:
import qualified Data.Map as Map
phoneBook :: Map.Map String String
phoneBook = Map.fromList $
    [("betty", "555"), ("bonnie", "452"), ("patsy", "493"), ("lucille", "205")]

In [87]:
:t Map.lookup


Map.lookup :: forall k a. Ord k => k -> Map k a -> Maybe a

In [88]:
Map.lookup "betty" phoneBook


Just "555"

In [90]:
Map.lookup "wendy" phoneBook


Nothing

In [91]:
Map.lookup "grace" phoneBook


Nothing

In [92]:
:t Map.insert


Map.insert :: forall k a. Ord k => k -> a -> Map k a -> Map k a

In [93]:
let newBook = Map.insert "grace" "341" phoneBook

In [95]:
Map.lookup "grace" newBook


Just "341"

In [96]:
:t Map.size


Map.size :: forall k a. Map k a -> Int

In [97]:
Map.size phoneBook


4

In [98]:
Map.size newBook


5

In [99]:
string2digits :: String -> [Int]
string2digits = map digitToInt . filter isDigit

In [100]:
string2digits "982-12312"


[9,8,2,1,2,3,1,2]

In [101]:
let intBook = Map.map string2digits phoneBook

In [103]:
:t intBook


intBook :: Map String [Int]

In [104]:
Map.lookup "betty" intBook


Just [5,5,5]

In [105]:
-- Map.fromListWith
phoneBookToMap :: (Ord k) => [(k, String)] -> Map.Map k String
phoneBookToMap xs = Map.fromListWith add xs
    where add number1 number2 = number1 ++ ", " ++ number2

In [106]:
phoneBook = [("betty", "555"), ("betty", "432")]

In [107]:
phoneBookToMap phoneBook


fromList [("betty","432, 555")]

In [109]:
Map.lookup "betty" $ phoneBookToMap phoneBook


Just "432, 555"

In [111]:
phoneBookToMap :: (Ord k) => [(k, a)] -> Map.Map k [a]
phoneBookToMap xs = Map.fromListWith (++) $ map (\(k, v) -> (k, [v])) xs

In [113]:
Map.lookup "betty" $ phoneBookToMap phoneBook


Just ["432","555"]

In [117]:
Map.fromListWith max [(2,3), (2,5), (2,100), (3, 29)]


fromList [(2,100),(3,29)]

In [115]:
Map.fromListWith (+) [(2, 3), (2,5), (2,100), (3,29), (3,22), (3,11)]


fromList [(2,108),(3,62)]