fmap的功能组成

时间:2017-09-20 12:14:10

标签: haskell

功能组合的简单定义是:

  newtype Compose f g a =
    Compose { getCompose :: f (g a) }
    deriving (Eq, Show)

  instance (Functor f, Functor g) => Functor (Compose f g) where
    fmap f (Compose fga) = Compose $ (fmap . fmap) f fga

fmap

现在我有以下示例:

  instance (Functor f, Functor g) => Functor (Compose f g) where
    fmap f (Compose fga) = Compose $ fmap f (fmap f fga)

然后我尝试在没有合成运算符的情况下编写* Couldn't match type `b' with `g b' `b' is a rigid type variable bound by the type signature for: fmap :: forall a b. (a -> b) -> Compose f g a -> Compose f g b at D:\haskell\chapter25\src\Twinplicative.hs:11:5 Expected type: f (g b) Actual type: f b * In the second argument of `($)', namely `fmap f (fmap f fga)' In the expression: Compose $ fmap f (fmap f fga) In an equation for `fmap': fmap f (Compose fga) = Compose $ fmap f (fmap f fga) * Relevant bindings include fga :: f (g a) (bound at D:\haskell\chapter25\src\Twinplicative.hs:11:21) f :: a -> b (bound at D:\haskell\chapter25\src\Twinplicative.hs:11:10) fmap :: (a -> b) -> Compose f g a -> Compose f g b (bound at D:\haskell\chapter25\src\Twinplicative.hs:11:5)

fmap

并且编译器抱怨:

{{1}}

如何在没有合成运算符的情况下撰写{{1}}以上?

2 个答案:

答案 0 :(得分:3)

当您提供类型为fmap的{​​{1}}时,您向g a -> g b最左侧应用程序提供的功能应为f。您可以使用a -> ba -> b将功能g a -> g b提升为fmap。外部fmap f的第二个参数应为fmap类型f (g a)

fga

答案 1 :(得分:2)

我喜欢Lee的回答,它清楚地说明了如何从头开始为Functor实现Compose实例。但是,我还认为值得回答一个密切相关的问题,即:如何从现有实例开始并机械地重写它以避免(.)函数组合?因此,我在这个答案中解决了这个问题。

由于(f . g) x = f (g x)(.)的定义等式,我们得出结论(fmap . fmap) f = fmap (fmap f)。将等式的两边应用于fga,我们得到:

(fmap . fmap) f fga = fmap (fmap f) fga