困惑功能在Haskell的函子实例(confused about function as insta

2019-06-23 22:14发布

FMAP的函子类型是:

fmap :: Functor f => (a -> b) -> f a -> f b

它看起来像,第一应用功能(一 - > b)至FA的参数来创建b型的结果,然后应用F到它,并且结果是FB

使用也许例如:

 fmap show (Just 1)
 result is : Just "1"

同样的话:

Just (show 1)

但是,当( - >)用作函子(在Control.Monad.Instances)

import Control.Monad.Instances
(fmap show Just) 1
result is : "Just 1"

也就是说,只要是申请,然后再应用展示。 在另一个例子中,结果是相同的:

 fmap (*3) (+100) 1
 result is 303

为什么不* 3,再+100?

Answer 1:

FMAP的函子类型是:

 fmap :: Functor f => (a -> b) -> fa -> fb 

它看起来像,第一应用功能(一 - > b)至FA的参数来创建b型的结果,然后应用F到它,并且结果是FB

这是类型fmap ,但你的是什么类型的意思解释是错误的。

你似乎认为fa有一个参数,而该参数的类型为a

考虑xs :: [a]

  • 或许xs = []
  • 或许xs = [x1]
  • 或许xs = [x1, x2]
  • ...

类型 fa是一个算符f使用单一类型的参数a 。 但是类型的 fa不一定采取的形式F x你可以从上面的第一和第三种情况看。

现在考虑fmap f xs

  • 也许fmap f xs = []
  • 也许fmap f xs = [f x1]
  • 也许fmap f xs = [f x1, f x2]
  • ...

我们不一定适用f所有(第一种情况)! 或者我们可以申请一次以上(第三种情况)。

我们做的是替换型的东西a ,有型的东西b 。 但是,我们离开了较大的结构不变---没有新元素的加入,没有元素去掉,它们的顺序保持不变。


现在,让我们想想仿函数(c ->) (请注意,一个仿函数只需要一种类型的参数,所以输入到(->)被固定)

做了c -> a甚至包含a ? 它可能不包含任何a s的一切,但它能够以某种神奇的一个凭空的时候,我们给它一个c 。 但是从结果fmap具有类型c -> b :我们只需要提供一个b出来的,当我们提出了一个c

所以我们可以说fmap fx = \y -> f (xy)

在这种情况下,我们将f需求---我们每次返回的功能被应用时, f被应用为好。



Answer 2:

fmap例如(->) r (即函数)是从字面上只是组合物。 从源本身 :

instance Functor ((->) r) where
    fmap = (.)

所以,在你的榜样,我们只需更换fmap(.)并做一些转换

fmap (*3) (+100) 1 => 
(.) (*3) (+100) 1  =>
(*3) . (+100) $ 1  => -- put (.) infix
(*3) (1 + 100)     => -- apply (+100)
(1 + 100) * 3         -- apply (*3)

也就是说, fmap对它们的功能组成从右到左(完全一样(.)这是明智的,因为它是(.)

看看它的另一种方式(!为(双)确认),我们可以使用类型签名:

-- general fmap
fmap :: Functor f => (a -> b) -> f a -> f b

-- specialised to the function functor (I've removed the last pair of brackets)
fmap :: (a -> b) -> (r -> a) -> r -> b 

类型,使得第一值r第三个参数)需要被转化成类型的值a (由r -> a功能),使a -> b函数可以将其转换类型的值b (结果)。



Answer 3:

需要被定义的方式,使各类工作了。 正如你所指出的类型, fmap是:

fmap :: Functor f => (a -> b) -> f a -> f b

让我们考虑的情况下,当函子f((->) c)

注:我们会真正喜欢写为(c ->)即从功能c ,但哈斯克尔不允许我们这样做。)

然后fa实际上是((->) ca)其等同于(c -> a) ,并且类似地对于fb ,因此我们有:

fmap :: (a -> b) -> (c -> a) -> (c -> b)

也就是说,我们需要采取两个功能:

  • f :: a -> b
  • g :: c -> a

并构建新功能

  • h :: c -> b

但是,只有一个做到这一点的方法:你必须申请g率先拿到类型的东西a ,然后应用f拿到类型的东西b ,这意味着你必须定义

instance Functor ((->) c) where
    fmap f g = \x -> f (g x)

或者,更简洁,

instance Functor ((->) c) where
    fmap = (.)


Answer 4:

fmap(->)被定义像fmap = (.) 所以, (fmap fg) x(f . g) xf (gx) 你的情况(*3) ((+100) 1)它等于3 * (100 + 1)这导致303



Answer 5:

为了形成一个功能类型,需要2个参数( - >),即单输入参数类型和返回类型。

仿函数只能取1个类型参数,所以你必须明确的输入参数类型(因为它是从第一个左到右),这使得该函数的返回类型为仿函数的类型参数。

所以对于功能(仿函数)A-> B,你需要给FMAP FF类型的函数B-> XXX比A-> XXX工作,这意味着功能FF后,才能A-应用> B以外是适用。



文章来源: confused about function as instance of Functor in haskell