-- a 相当于 泛型
data Maybe a = Nothing | Just a
ghci> Just "Haha"
Just "Haha"
ghci> Just 84
Just 84ghci> :t Just "Haha"
Just "Haha" :: Maybe [Char]
ghci> :t Just 84Just 84 :: (Num t) => Maybe t
ghci> :t Nothing
Nothing :: Maybe a
Car的案例
1
2
3
4
5
6
7
8
9
10
11
12
dataCar = Car{ company :: String
, model :: String
, year :: Int
}deriving(Show)-- 也可以改为这样, 但是可能没有用处dataCar a b c = Car{ company :: a
, model :: b
, year :: c
}deriving(Show)tellCar :: Car -> StringtellCar (Car {company = c, model = m, year = y}) = "This " ++ c ++ " " ++ m ++ " was made in " ++ show y
Vector(三维矢量)
1
2
3
dataVecotr a = Vector a a a deriving(Show)vplus :: (Num t) => Vector t -> Vector t -> Vector t
(Vector i j k) `vplus` (Vector l m n) = Vector (i+l) (j+m) (k+n)
Derived instances
TypeClass, 在 Java, C++ 等语言中, 类就像是蓝图,
我们可以根据它来创造对象保存对象并执行操作.
TypeClass 更像是接口, 我们不是靠它构造数据,而是给既有的数据类型描述行为.
什么东西若可以判定相等性,我们就可以让它成为 Eq 类型类的 instance。什么东西若可以比较大小,
那就可以让它成为 Ord 类型类的 instance。
data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)
-- 定义单节点树
single :: a -> Tree a
singleton x = Node x EmptyTree EmptyTree
-- 插入
treeInsert :: (Ord a) => a -> Tree a -> Tree a
treeInsert x EmptyTree = singleton x
treeInsert x (Node x left right)
| x == a = Node x left right
| x < a = Node a (treeInsert x left) right
| x > a = Node a left (treeInsert x right)
-- 查找
treeElem :: (Ord a) => a -> Tree a -> Bool
treeElem x EmptyTree = False
treeElem x (Node a left right)
| x == a = True
| x < a = treeElem x left
| x > a = treeElem x right
-- Prelude 中 Eq 如何被定义classEq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
x == y = not (x /= y)
x /= y = not (x == y)
dataTrafficLight = Red | Yellow | Green-- 可以透过 derive 让他成为 Eq 的instance-- 手动编写instanceEqTrafficLightwhereRed == Red = TrueGreen == Green = TrueYellow == Yellow = True
_ == _ = FalseinstanceShowTrafficLightwhere
show Red = "Red light"
show Yellow = "Yellow light"
show Green = "Green light"-- 类型约束, 定义一个类型为 Num 之前,必须先为他定义 Eq 的 instanceclass(Eqa) => Num a where-- instance Eq Maybe where, 错误用法-- 是不是可以理解为类型 (Maybe a) 才是一个完整的类型instanceEq(Maybem)whereJust x == Just y = x == y
Nothing == Nothing = True
_ == _ = False-- 最终极版本instance(Eqm) => Eq(Maybem)whereJust x == Just y = x == y
Nothing == Nothing = True
_ == _ False
classYesNo a where
yesno :: a -> BoolinstanceYesNoIntwhere
yesno 0 = False
yesno _ = TrueinstanceYesNo [a] where
yesno [] = False
yesno _ = True-- 标准函式库中的一个函数,他接受一个参数并回传相同的东西instanceYesNoBoolwhere
yesno = id
yesnoIf :: (YesNo y) => y -> a -> a -> a
yesnoIf yesnoVal yesResult noResult =
if yesno yesnoVal then yesResult else noResult
ghci> yesnoIf [] "YEAH!""NO!""NO!"ghci> yesnoIf [2,3,4] "YEAH!""NO!""YEAH!"ghci> yesnoIf True"YEAH!""NO!""YEAH!"ghci> yesnoIf (Just500) "YEAH!""NO!""YEAH!"ghci> yesnoIf Nothing"YEAH!""NO!""NO!"
Functor typeclass
Functor 这个 typeclass,基本上就代表可以被 map over 的事物
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- f 代表一个类型构造子 Maybe(不是 Maybe a), 不是具体类型-- 可以当作盒子的类型可能就是一个 functor, 如 List, Maybe-- 实例化后: (a -> b) -> Tree a -> Tree b-- (a -> b) -> Maybe a -> Maybe bclassFunctor f where
fmap :: (a -> b) -> f a -> f b
-- map :: (a -> ) -> [a] -> [b]-- 注意这里没有写 [a]instanceFunctor [] where
fmap = map
-- 注意 这边没有写 Maybe ainstanceFunctorMaybewhere
fmap f (Just x) = Just (f x)
fmap f Nothing = Nothing
-- 一个 * 代表这个类型是具体类型ghci> :k IntInt :: *
-- * -> * 代表这个类型构造子接受一个具体类型并回传一个具体类型ghci> :k MaybeMaybe :: * -> *
ghci> :k MaybeIntMaybeInt :: *
-- f 必须是 * -> * kindclassFunctor f where
fmap :: (a -> b) -> f a -> f b
-- a 是 *-- j 是 * -> * -- t 是 * -> (* -> *) -> *classTofu t where
tofu :: j a -> t a j
-- a 是 *-- b 是 * -> *dataFrank a b = Frank{frankField :: ba}deriving(Show)-- Barry 是 (* -> *) -> * -> * -> *dataBarry t k p = Barry{ yabba :: p, dabba :: tk }instanceFunctor(Barryab)where
fmap :: (a -> b) -> Barry c d a -> Barry c d b
instanceFunctor(Barryab)where
fmap f (Barry {yabba = x, dabba =})