简体   繁体   English

fmap的功能组成

[英]Function composition of fmap

The simple definition of function composition is: 函数组成的简单定义是:

f ( g x)

or 要么

(f . g) $ x

Now I have following example: 现在,我有以下示例:

  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

Then I try to write fmap without composition operator as: 然后,我尝试编写不带合成运算符的fmap

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

and the compiler complains: 编译器抱怨:

* 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)

How to compose fmap above without composition operator? 如何在没有合成运算符的情况下撰写以上fmap

The function you provide to the leftmost application of fmap should have type ga -> gb while you are providing f which has type a -> b . 提供给fmap最左侧应用程序的fmap类型应该为fmap ga -> gb而提供的f具有类型fmap a -> b You can lift a function a -> b to ga -> gb using fmap ie fmap f . 您可以使用fmapfmap ffmap fmap f a -> b提升为fmap ga -> gb The second argument to the outer fmap should have type f (ga) which is the type of fga : 外部fmap的第二个参数应为f (ga)类型,即fga的类型:

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

I like Lee's answer, which states clearly how you could implement the Functor instance for Compose yourself from scratch. 我喜欢李的回答,其中明确规定你怎么能实现Functor实例Compose自己从头开始。 However, I also thought it worth answering a closely related question, which is: how do I start from the existing instance and mechanically rewrite it to avoid the (.) function composition? 但是,我也认为有必要回答一个密切相关的问题,那就是:如何从现有实例开始并机械地重写它以避免(.)函数组合? Therefore I tackle that question in this answer. 因此,我在这个答案中解决了这个问题。

Since (f . g) x = f (gx) is the defining equation of (.) , we conclude (fmap . fmap) f = fmap (fmap f) . 由于(f . g) x = f (gx) (fmap . fmap) f = fmap (fmap f) (f . g) x = f (gx)(.)的定义方程,因此我们得出(fmap . fmap) f = fmap (fmap f) Applying both sides of the equation to fga , we get: 将方程的两边应用于fga ,我们得到:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM