(fmap.fmap)for Applicative

时间:2018-01-02 08:55:02

标签: haskell applicative

fmap.fmap允许我们将“两层深层”变成一个仿函数:

fmap.fmap :: (a -> b) -> f (g a) -> f (g b)

这对应用函子也有可能吗?假设我想通过使用它们的应用属性来组合Just (+5)[1,2,3]。我可以想出一个明显的方法来做到这一点,但对我来说这似乎并不重要。

(<*>).(<*>)没有确凿的类型签名:

((<*>).(<*>)) :: (a1 -> a2 -> b) -> ((a1 -> a2) -> a1) -> (a1 -> a2) -> b
-- where I would expect something like:
-- ((<*>).(<*>)) :: f (g (a -> b)) -> f (g a) -> f (g b)

是否可以这种方式撰写Just (+5)[1,2,3]

编辑:

第一步是使用:

  • pure $ Just (+5)fmap pure [1,2,3]
  • fmap pure (Just (+5)pure [1,2,3]

但我仍然不知道如何撰写这些......

编辑:

有一个通用的方法来组成一个函数f (g (a -> b)f (g a)会很好,我不只是在寻找上述情况的解决方案,它只是作为一个这种功能的示例输入。基本上我想要一个功能:

(<***>) :: f (g (a -> b)) -> f (g a) -> f (g b)

2 个答案:

答案 0 :(得分:4)

liftA2具有与fmap类似的组合属性。

liftA2 f            ::    f a  ->    f b  ->    f c
(liftA2 . liftA2) f :: g (f a) -> g (f b) -> g (f c)

所以你可以写

(liftA2 . liftA2) ($) (pure (Just (+5))) (fmap pure [1,2,3]) :: [Maybe Integer]

即,(<***>) = (liftA2 . liftA2) ($)。 (很像(<*>) = liftA2 ($)

另一种看待它的方法是,应用函子的组合是一个应用函子,这是由Data.Functor.Compose具体化的:

{-# LANGUAGE ScopedTypeVariables, PartialTypeSignatures #-}

import Data.Functor.Compose
import Data.Coerce

(<***>) :: forall f g a b. (Applicative f, Applicative g)
        => f (g (a -> b)) -> f (g a) -> f (g b)
(<***>) = coerce ((<*>) :: Compose f g (a -> b) -> _)

coerce的要点是要显示(<***>) 适用于正确类型的(<*>);我们也可以手动展开

f <***> x = getCompose $ Compose f <*> Compose x

答案 1 :(得分:2)

我们有f (g (a->b))。要从g a -> g b获取g (a->b),我们只需要<*>,但g (a->b)包含在f中。幸运的是f是一个Functor,所以我们可以fmap覆盖它。

Prelude> :t fmap (<*>)
fmap (<*>)
  :: (Functor f1, Applicative f) =>
     f1 (f (a -> b)) -> f1 (f a -> f b)
Prelude>

那更好,我们现在有一个包含在Functor中的函数。如果此Functor恰好是申请人,我们可以通过它申请<*>

Prelude> :t (<*>) . fmap (<*>)
(<*>) . fmap (<*>)
  :: (Applicative f, Applicative f1) =>
     f1 (f (a -> b)) -> f1 (f a) -> f1 (f b)
Prelude>

正是医生所要求的。

Prelude> let (<***>) = (<*>) . fmap (<*>)
Prelude> [Just (+2), Just (*3), Nothing] <***> [Just 7, Just 42, Nothing]
[Just 9,Just 44,Nothing,Just 21,Just 126,Nothing,Nothing,Nothing,Nothing]
Prelude>