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 

三者等价

posted @ 2021-11-13 20:03  liankewei123456  阅读(87)  评论(0编辑  收藏  举报