Haskell学习笔记--functor/applicative/Effective programming
Haskell 学习笔记 -- functor / applicative
这部分肯定是 Haskell 中最最抽象的了,我上课就没懂(
还有什么范畴论,自闭了
Functor 函子
函子的意思是一类容器,它里面可以装各种东西
比如 [] \ Maybe \ Tree
要让一个数据结构成为 Functor , 必须支持函数 fmap
1 instance Functor [] where 2 --fmap :: ( a -> b ) -> f a - f b 3 fmap g [] = [] 4 fmap g (x:xs) = fmap g xs ++ [g x]
fmap 相当于把函数作用到数据结构的每一个位置上
Applicative
多个参数的fmap(
很抽象举例子
fmap0 :: a -> f a fmap1 :: a -> b -> f a -> f b fmap2 :: a -> b -> c -> f a -> f b -> f c
applicative 需要实现两个函数:
pure :: a -> f a (<*>) :: f ( a -> b ) -> f a -> f b -- <*> 是左结合的
然后就可以改写了
fmap2 g x y = pure g <*> x <*> y
对于Maybe / [] / IO 来说
instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing g :: a -> b mx :: f a (Just g ) <*> mx = fmap g mx instance Applicative [] where pure x = [x] gs <*> xs = [g x | g <- gs , x <- xs ] -- pure (*) <*> [1,2] <*> [3,4] -- [3,4,6,8]
instance Applicative IO where
pure = return
mg <*> mx = do {g <- mg; x <- mx; return (g x)}
IO 的一个具体例子
getChars :: Int -> IO String getChats 0 = return [] --(:) :: a -> [a] -> [a] --pure (:) -> IO (a -> [a] -> [a] ) getChars n = pure (:) <*> getChar <*> getChars (n-1)
Effective progframming
有效的编程(x
看来我以前的都是无效的
这里有效可能更像“有副作用”
比如说 Maybe 可能失败(Nothing)
[] 可能有多种解
IO 附带输入输出
所以我们也可以用 applicative 改装函数
标准库中有一个函数:sequenceA 用于一个序列里头装函子 出来的是函子里头装序列
(这里的函子是有副作用的,见上,所以可以将函子也理解为作用
Evaluate each action in the structure from left to right, and collect the results.
sequenceA :: Applicative f => [f a] -> f [a] sequenceA (x:xs) = pure (:) <*> x <*> sequenceA xs pure (:) :: f ( a -> [a] -> [a] ) getChars :: Int -> IO string getChars n = sequenceA (replicate n getChar ) -- getChar :: IO char -- replicate :: Int -> a -> [a] --replicate n getChar :: [IO char]
最后补充一种等价写法:
pure g <*> x1 g <$> x1 fmap g x1
三者等价