haskell Applicative Functor

如果我们的有一个 functor 里面是 Just (3 *) 还有另一个 functor 里面是 Just 5,但我们想要把第一个 Just (3 *) map over Just 5 呢?如果是普通的 functor,那就没救了。因为他们只允许 map 一个普通的函数。即使我们用 \f -> f 9 来 map 一个装了很多函数的 functor,我们也是使用了普通的函数。我们是无法单纯用 fmap 来把包在一个 functor 的函数 map 另一个包在 functor 中的值。我们能用模式匹配Just 来把函数从里面抽出来,然后再 map Just 5,但我们是希望有一个一般化的作法,对任何 functor 都有效。

看看 Applicative 这个 typeclass。他位在 Control.Applicative 中,在其中定义了两个函数pure 跟 <*>。他并没有提供缺省的实作,如果我们想使用他必须要为他们 applicative functor 的实作。typeclass 定义如下:

class (Functor f) => Applicative f where   
    pure :: a -> f a   
    (<*>:: f (a -> b) -> f a -> f b

  • Applicative 是一个 Functor, 所以他也有fmap 
  • pure 应该要接受一个值,然后回传一个包含那个值的 applicative functor。(对于 pure 比较好的说法是把一个普通值放到一个缺省的 context 下,一个最小的 context 但仍然包含这个值。)
  • <*> 则是接受一个装有函数的 functor 跟另一个 functor,然后取出第一个 functor 中的函数将他对第二个 functor 中的值做 map。(左结合)

instance Applicative Maybe where   
    pure = Just   
    Nothing <*> _ = Nothing   
ghci> pure (+) <*> Just 3 <*> Just 5   
Just 8 
pure f <*> x  等于  fmap f x 
Control.Applicative  会 export 一个函数   <$> ,他基本上就是中缀版的  fmap 。他是这么被定义的:
(<$>:: (Functor f) => (a -> b) -> f a -> f b   
f <$> x = fmap f x
说明:要记住类型变量跟参数的名字还有值绑定的名称不冲突。 f  在函数的类型宣告中是类型变量,说明  f  应该要满足  Functor  typeclass 的条件。而在函数本体中的  f  则表示一个函数,我们将他 map over x。我们同样用  f  来表示他们并代表他们是相同的东西。

       可以将一个普通的函数套用在 applicative functor 上真不错。只要稍微写一些 <$> 跟 <*> 就可以把函数变成 applicative style,可以操作 applicatives 并回传 applicatives。

   

instance Applicative [] where   
    pure x = [x]   
    fs <*> xs = [f x | f <- fs, x <- xs]

instance Applicative ((->) r) where   
    pure x = (\_ -> x)   
    f <*> g = \x -> f x (g x)
当我们用  pure  将一个值包成 applicative functor 的时候,他产生的结果永远都会是那个值。也就是最小的 context。那也是为什么对于 function 的  pure  实作来讲,他就是接受一个值,然后造一个函数永远回传那个值,不管他被喂了什么参数。如果你限定  pure  的类型至  (->) r  上,他就会是 pure :: a -> (r -> a)

ghci> :t (+) <$> (+3) <*> (*100)   
(+) <$> (+3) <*> (*100:: (Num a) => a -> a   
ghci> (+) <$> (+3) <*> (*100) $ 5   
508
ghci> (\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5   
[8.0,10.0,2.5]
当我们做 (+) <$> Just 3 <*> Just 5 ,我们是用 +  套用在一些可能有或可能没有的值上,所以结果也会是可能有或没有。当我们做  (+) <$> (+10) <*> (+5) ,我们是将  +  套用在  (+10)  跟 (+5)  的结果上,而结果也会是一个函数,当被喂给一个参数的时候会产生结果。

instance Applicative ZipList where   
        pure x = ZipList (repeat x)   
        ZipList fs <*> ZipList xs = ZipList (zipWith (\f x -> f x) fs xs)

111

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值