类型类练习题
为黄总精心设计,不要谢我,请我喝奶茶、吃榨菜即可。
第一题
给一下数据类型:
data MilkTea =
{ hasBoba :: Bool
, cupSize :: Int
} deriving Show
手工定义 Eq 实例。
给出以下值的类型:
hasBoba
cupSize
定义函数 view, set, lHasBoba 并满足以下不变量:
view lHasBoba :: MilkTea -> Bool
view lHasBoba tea = hasBoba tea
set lHasBoba :: Bool -> MilkTea -> MilkTea
set lHasBoba x tea = tea { hasBoba = x }
提示,可以定义数据类型 LHasBoba 如下:
data LHasBoba = LHasBoba
{ view :: MilkTea -> Bool
, set :: Bool -> MilkTea -> MilkTea
}
lHasBoba = LHasBoba
{ view = ...
, set = ...
}
上述的 LHasBoba 被称为 lens。试定义一个通用的 Lens:
data Lens s a = Lens
{ view :: s -> a
, set :: a -> s -> s
}
并给出 lHasBoba 与 lCupSize
第二题
class Functor f where
fmap :: (a -> b) -> f a -> f b
见阅读材料。
给出以下数据类型的 Functor 实例:
data Maybe a = Just a | Nothing
data [a] = a : [a] | []
data Tree a = Leaf a | Branch (Tree a) (Tree a)
data Identity a = Identity { runIdentity :: a }
data Const a = Const { runConst :: a }
不得使用 DeriveFunctor 扩展。
Lens s a 还可以定义为:
type Lens s a = forall f. Functor f => (a -> f a) -> s -> f s
注:需要打开扩展 RankNTypes,自行谷歌 GHC 开启扩展的方法。
根据上述 Lens 定义,重新定义 view 与 set。提示:使用 Identity 和 Const。
第三题
第二题陈述了一个事实,这两种 Lens s a 的定义同构,即存在如下两个函数:
data Lens s a = Lens
{ view :: s -> a
, set :: a -> s -> s
}
type Lens' s a = formal f. Functor f => (a -> f a) -> s -> f s
lensToLens' :: Lens s a -> Lens' s a
lens'ToLens :: Lens' s a -> Lens s a
试给出两者定义。
第四题
data Expr = Lit Int
| Add Expr Expr
| Mul Expr Expr
定义以下函数:
eval :: Expr -> Int