组成两个函数是什么意思?

akb*_*ggs 26 theory haskell functor

Haskell Typeclassopedia 3.2节的练习5要求在声明中提供证据或反例

两个Functors的组合也是一个Functor.

我一开始以为这是在讨论组合fmap由两个单独的a实例定义的方法Functor,但这并没有多大意义,因为就我所知,类型不会匹配.对于两种类型,f并且f',类型fmap将是fmap :: (a -> b) -> f a -> f bfmap :: (a -> b) -> f' a -> f' b,并且实际上看起来并不可组合.那么组成两个是什么意思Functors呢?

Dan*_*ner 26

A Functor给出两个映射:一个在类型级别上映射类型到类型(这是xin instance Functor x where),一个在计算级别上映射函数到函数(这是xin fmap = x).您正在考虑编写计算级映射,但应考虑编写类型级映射; 例如,给定

newtype Compose f g x = Compose (f (g x))
Run Code Online (Sandbox Code Playgroud)

你能写吗

instance (Functor f, Functor g) => Functor (Compose f g)
Run Code Online (Sandbox Code Playgroud)

?如果没有,为什么不呢?

  • 这是一个很好的答案,解释了Typeclassopedia练习,但没有给出解决方案. (2认同)

Lui*_*las 18

这是怎么谈的是的组成类型构造喜欢[]Maybe不喜欢的功能组成fmap.因此,例如,有合成的两种方式 []Maybe:

newtype ListOfMabye a = ListOfMaybe [Maybe a]
newtype MaybeOfList a = MaybeOfList (Maybe [a])
Run Code Online (Sandbox Code Playgroud)

声明两个组合Functors是一种Functor意味着有一种Functor为这些类型编写实例的公式化方法:

instance Functor ListOfMaybe where
    fmap f (ListOfMaybe x) = ListOfMaybe (fmap (fmap f) x) 

instance Functor MaybeOfList where
    fmap f (MaybeOfList x) = MaybeOfList (fmap (fmap f) x)
Run Code Online (Sandbox Code Playgroud)

实际上,Haskell平台附带了一个模块Data.Functor.Compose,它为您提供了一个Compose"免费"执行此操作的类型:

import Data.Functor.Compose

newtype Compose f g a = Compose { getCompose :: f (g a) }

instance (Functor f, Functor g) => Functor (Compose f g) where
    fmap f (Compose x) = Compose (fmap (fmap f) x)
Run Code Online (Sandbox Code Playgroud)

ComposeGeneralizedNewtypeDeriving扩展名特别有用:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

newtype ListOfMaybe a = ListOfMaybe (Compose [] Maybe a)
   -- Now we can derive Functor and Applicative instances based on those of Compose
   deriving (Functor, Applicative)
Run Code Online (Sandbox Code Playgroud)

注意,两个Applicatives 的组成也是一个Applicative.因此,由于[]MaybeApplicativeS,所以是Compose [] MaybeListOfMaybe.编写Applicatives是一种非常简洁的技术,这些技术现在正逐渐变得越来越普遍,作为monad变换器的替代品,适用于不需要monad全部功能的情况.

  • 肯定是这里所有答案中最有用的.让我进一步问你:当你写fmap f(撰写x)时x的类型是什么?我会说它是fga,但我仍然很难想象计算(fmap(fmap f)x).要对getCompose更加思考.注意:我知道字母"f"在这里用于两个不同的角色. (2认同)

Ste*_*ehl 13

在这里考虑分类解释确实很有帮助,仿函数F: C -> D将对象(值)和态射(函数)从一个类别C中的对象和态射带到一个类别中的对象和态射D.

对于第二个仿函数G : D -> E,仿函数的组合G . F : C -> E只是将F fmap变换的密码域作为转换的领域G fmap.在Haskell中,这是通过一个新的类型展开来完成的.

import Data.Functor

newtype Comp f g a = Comp { unComp :: f (g a) }

compose :: f (g a) -> Comp f g a
compose = Comp

decompose :: Comp f g a -> f (g a)
decompose = unComp

instance (Functor f, Functor g) => Functor (Comp f g) where
  fmap f = compose . fmap (fmap f) . decompose
Run Code Online (Sandbox Code Playgroud)

  • 嘿! 没有破坏者!= P (2认同)

kqr*_*kqr 12

两个函数的组合是当你将一个函数放在另一个函数中时,例如

round (sqrt 23)
Run Code Online (Sandbox Code Playgroud)

这是两个功能的组成roundsqrt.类似地,两个仿函数的组合是当你将一个仿函数放在另一个仿函数中时,例如

Just [3, 5, 6, 2]
Run Code Online (Sandbox Code Playgroud)

List是一个仿函数,Maybe也是.如果你试图找出fmap应该对上面的值做什么,你可以得到一些直觉来解释为什么他们的作品也是一个仿函数.当然它应该映射内部仿函数的内容!