Functor中的fmap类型是:
fmap :: Functor f => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
看起来,首先将函数(a - > b)应用于fa的参数以创建类型b的结果,然后对其应用f,结果为fb
使用Maybe a例如:
fmap show (Just 1)
result is : Just "1"
Run Code Online (Sandbox Code Playgroud)
同说:
Just (show 1)
Run Code Online (Sandbox Code Playgroud)
但是当( - >)用作Functor时(在Control.Monad.Instances中)
import Control.Monad.Instances
(fmap show Just) 1
result is : "Just 1"
Run Code Online (Sandbox Code Playgroud)
也就是说,Just首先应用,然后显示应用.在另一个例子中,结果是相同的:
fmap (*3) (+100) 1
result is 303
Run Code Online (Sandbox Code Playgroud)
为什么不*3先,然后+100?
huo*_*uon 33
(即函数)的fmap
实例(->) r
实际上只是组合.从源本身:
instance Functor ((->) r) where
fmap = (.)
Run Code Online (Sandbox Code Playgroud)
所以,在你的榜样,我们就可以代替fmap
用(.)
,并做一些转换
fmap (*3) (+100) 1 =>
(.) (*3) (+100) 1 =>
(*3) . (+100) $ 1 => -- put (.) infix
(*3) (1 + 100) => -- apply (+100)
(1 + 100) * 3 -- apply (*3)
Run Code Online (Sandbox Code Playgroud)
也就是说,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
Run Code Online (Sandbox Code Playgroud)
所以首先r
需要将type (第三个参数)的值转换为类型的值a
(通过r -> a
函数),以便a -> b
函数可以将其转换为类型的值b
(结果).
dav*_*420 26
Functor中的fmap类型是:
Run Code Online (Sandbox Code Playgroud)fmap :: Functor f => (a -> b) -> f a -> f b
看起来,首先将函数(a - > b)应用于fa的参数以创建类型b的结果,然后对其应用f,结果为fb
这是类型fmap
,但你对这种类型的解释是错误的.
您似乎假设f a
有一个参数,并且该参数具有类型a
.
考虑xs :: [a]
:
xs = []
.xs = [x1]
.xs = [x1, x2]
.该类型 f a
是f
具有单个类型参数的仿函数a
.但是,从上面的第一和第三种情况可以看出,类型的值f a
不一定采用这种形式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 f x = \y -> f (x y)
.
在这种情况下,我们f
按需应用---每当我们返回的函数被应用时,f
也会应用.
Chr*_*lor 17
它需要被定义的方式,使各类工作了.正如您所指出的那样,类型fmap
是:
fmap :: Functor f => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
让我们考虑仿函数的f
情况((->) c)
(注意:我们实际上喜欢将其写为(c ->)
,即函数c
,但Haskell不允许我们这样做.)
那么f a
实际上((->) c a)
,这相当于(c -> a)
,同样f b
如此,所以我们有:
fmap :: (a -> b) -> (c -> a) -> (c -> b)
Run Code Online (Sandbox Code Playgroud)
即我们需要采取两个功能:
f :: a -> b
g :: c -> a
并构建一个新的功能
h :: c -> b
但是只有一种方法可以做到这一点:你必须首先申请g
获得类型的东西a
,然后申请f
获得类型的东西b
,这意味着你必须定义
instance Functor ((->) c) where
fmap f g = \x -> f (g x)
Run Code Online (Sandbox Code Playgroud)
或者,更简洁,
instance Functor ((->) c) where
fmap = (.)
Run Code Online (Sandbox Code Playgroud)
fmap
for (->)
定义为fmap = (.)
.所以,(fmap f g) x
是(f . g) x
的f (g x)
.在你的情况下(*3) ((+100) 1)
,等于3 * (100 + 1)
导致的结果303
.