繁体   English   中英

混淆功能作为haskell中Functor的实例

[英]confused about function as instance of Functor in haskell

Functor中的fmap类型是:

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

看起来,首先将函数(a - > b)应用到fa的参数以创建类型b的结果,然后对其应用f,结果为fb

使用Maybe a例如:

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

同说:

Just (show 1)

但是当( - >)用作Functor时(在Control.Monad.Instances中)

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

也就是说,Just首先应用,然后显示应用。 在另一个例子中,结果是相同的:

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

为什么不* 3先,然后+100?

(->) r (即函数)的fmap实例实际上只是组合。 源本身

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的值(结果)。

Functor中的fmap类型是:

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

看起来,首先将函数(a - > b)应用到fa的参数以创建类型b的结果,然后对其应用f,结果为fb

这是fmap的类型,但是你对这种类型的解释是错误的。

您似乎假设fa有一个参数,并且该参数的类型为a

考虑xs :: [a]

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

类型 fa是具有单个类型参数a的仿函数f 但是fa类型的不一定采用F x的形式,正如您从上面的第一和第三种情况中可以看到的那样。

现在考虑fmap f xs

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

我们根本不一定申请f (第一种情况)! 或者我们可以多次应用它(第三种情况)。

我们所做的是用类型b的东西替换类型a东西。 但是我们保留了较大的结构 - 没有添加新元素,没有删除元素,它们的顺序保持不变。


现在让我们考虑一下仿函数(c ->) (请记住,仿函数只接受一个类型参数,因此(->)的输入是固定的。)

c -> a是否包含a 它可能根本不包含任何a s,但是当我们给它一个c时,它可以用某种方式用空气来魔术。 但是fmap的结果是类型c -> b :当我们看到c时,我们只需要提供一个b

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

在这种情况下,我们按需应用f - 每次返回我们返回的函数时, f也会被应用。

需要定义它以使类型工作。 正如您所指出的, fmap的类型是:

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

让我们考虑仿函数f((->) c)

注意:我们实际上想把它写成(c ->) ,即来自c函数,但是Haskell不允许我们这样做。)

那么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 = (.)

fmap(->)被定义像fmap = (.) 因此, (fmap fg) x(fmap fg) x (f . g) xf (gx) 在你的情况下(*3) ((+100) 1) ,等于3 * (100 + 1) ,结果为303

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

Functor只能接受1个类型参数,因此您必须确定输入参数类型(因为它是从左到右的第一个),这使得函数的返回类型成为Functor的类型参数。

所以对于函数(Functor)a-> b,你需要给fmap一个类型为b-> xxx的函数ff而不是a-> xxx才能工作,这意味着函数ff只能在a-> b之后应用适用。

暂无
暂无

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

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