(fmap.fmap)for Applicative

问题描述 投票:3回答:2

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)
haskell applicative
2个回答
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

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恰好是一个Applicative,我们可以通过它来应用<*>

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>
© www.soinside.com 2019 - 2024. All rights reserved.