• 导入模块 import Data.List
  • 导入模块必须放置在任何函数的定义之前
  • 导入模块后,模块内的函数就进入了全局命名空间
  • GHCi 导入模块 :m + Data.List Data.Map Data.Set
  • 导入部分函数 import Data.List (nub, sort)
  • 忽略部分函数 import Data.List hiding (nub)
  • 限定导入 import qualified Data.Map
  • 限定导入后的函数需要指定前缀 Data.Map.filter
  • 限定导入可以使用别名 import qualified Data.Map as M
import Data.List
numUniques :: (Eq a) => [a] -> Int
numUniques = length . nub

foldl 左折叠在执行过程中构建了一个大的延迟计算栈,直到折叠的目标变成 [] 之后,才真正开始对先前延迟的进行求值。对于大列表来说,这就容易造成栈溢出,或者内存占用过多。使用 Data.List.foldl' 可以进行严格左折叠。两个函数的计算过程类似:

  foldl (+) 0 [1,2,3]
= foldl (+) (0+1) [2,3]
= foldl (+) ((0+1)+2) [3]
= foldl (+) (((0+1)+2)+3) [] 
    -- The above will not cause stack overflow
    -- because they are allocated on the heap.
    -- However, the following will
    -- because all operands will be pushed to the stack.
= ((0+1)+2)+3
= (1+2)+3
= 3+3
= 6

  foldl' (+) 0 [1,2,3]
= foldl' (+) 1 [2,3]
= foldl' (+) 3 [3]
= foldl' (+) 6 []
= 6
  • Maybe 数据类型
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

phoneBook = 
    [("betty", "555-2938")
    ,("patsy", "493-2928")
    ,("wendy", "939-8282")
]
findKey "patsy" phoneBook -- Just "493-2928"
findKey "penny" phoneBook -- Nothing
  • 编写模块
  • 要导出的部分写在 moudle 里面
-- Geometry/Sphere.hs:
module Geometry.Sphere
( volume
, area
) where

volume :: Float -> Float
volume radius = (4.0 / 3.0) * pi * (radius ^ 3)

area :: Float -> Float
area radius = 4 * pi * (radius ^ 2)


-- Geometry/Cuboid.hs
module Geometry.Cuboid
( volume
, area
) where

volume :: Float -> Float -> Float -> Float
volume a b c = rectArea a b * c

area :: Float -> Float -> Float -> Float
area a b c = rectArea a b * 2 + rectArea a c * 2 + rectArea c b * 2

rectArea :: Float -> Float -> Float
rectArea a b = a * b


-- Use:
import qualified Geometry.Sphere as Sphere
import qualified Geometry.Cuboid as Cuboid

Sphere.area 10
Cuboid.area 10 10 10
  • data 定义新的数据类型,等号左端的部分为类型名称,等号右端的为值构造器
  • 类型名和值构造器首字母必须大写
  • 一个值构造器可以有若干字段
  • deriving (Show) 会将该类型置于 Show 类型类之中
  • 在一个类型仅有唯一值构造器时,类型名与值构造器名称相同是非常常见的
  • 可以编写人民喜闻乐见的辅助函数
data Point = Point Float Float deriving (Show)
data Shape = Circle Point Float | Rectangle Point Point deriving (Show)

area :: Shape -> Float
area (Circle _ r) = pi * r ^ 2
area (Rectangle (Point x1 y1) (Point x2 y2)) = (abs $ x2 - x1) * (abs $ y2 - y1)

area (Rectangle (Point 0 0) (Point 100 100))   -- 10000.0
area (Circle (Point 0 0) 10)                   -- 314.15927



nudge :: Shape -> Float -> Float -> Shape
nudge (Circle (Point x y) r) dx dy = Circle (Point (x+dx) (y+dy)) r
nudge (Rectangle (Point x1 y1) (Point x2 y2)) dx dy = Rectangle (Point (x1+dx) (y1+dy)) (Point (x2+dx) (y2+dy))

baseCircle :: Float -> Shape
baseCircle r = Circle (Point 0 0) r

baseRect :: Float -> Float -> Shape
baseRect width height = Rectangle (Point 0 0) (Point width height)

makeCircle :: Float -> Float -> Float -> Shape
makeCircle x y r = nudge (baseCircle r) x y

makeRect :: Float -> Float -> Float -> Float -> Shape
makeRect x1 y1 width height = nudge (baseRect width height) x1 y1

makeRect 60 23 40 100       -- Rectangle (Point 60.0 23.0) (Point 100.0 123.0)
  • 使用记录类型
data Car = Car { company :: String
               , model :: String
               , year :: Int
               } deriving (Show)

tellCar :: Car -> String
tellCar (Car {company = c, model = m, year = y}) =
    "This " ++ c ++ " " ++ m ++ " was made in " ++ show y

mycar = Car {company="Ford", model="Mustang", year=1967}
tellCar mycar    -- "This Ford Mustang was made in 1967"