如何理解 \g x -> fmap ($) g x 中的仿函数
How to understand functor in \g x -> fmap ($) g x
我是 Haskell 的初学者。我知道函数 fmap
有两个参数 ((a->b) -> f a ->
) 和 returns 一个仿函数 (f b
),但我无法理解下面的 lambda 表达式
*Main> :t \g x -> fmap ($) g x
\g x -> fmap ($) g x :: (t -> a -> b) -> t -> a -> b
仿函数在哪里?
顺便说一句,我已经尝试了几个不同括号的相似表达式,它们给出了不同的结果:
*Main> :t \g x -> fmap ($) (g x)
\g x -> fmap ($) (g x) :: Functor f => (t -> f (a -> b)) -> t -> f (a -> b)
*Main> :t \g x -> fmap $ g x
\g x -> fmap $ g x :: Functor f => (t -> a -> b) -> t -> f a -> f b
我不明白这个。
来自
\g x -> fmap ($) g x :: (t -> a -> b) -> t -> a -> b
我们有
g :: t -> a -> b
x :: t
fmap ($) g :: t -> a -> b
fmap ($) g x :: a -> b
要找函子,写g
的类型作为类型级的应用F X
就可以了F
和X
.
我们有
t -> a -> b = (->) t (a -> b)
因此,F = (->) t
和 X = (a -> b)
。
因此,fmap
调用在 (->) t
函子中起作用。我们需要将 t -> a -> b
视为 a -> b
类型的值“包装”在函子 (->) t
.
下
现在,我们有
($) :: (a->b) -> a -> b
-- which means
($) :: (a->b) -> (a -> b)
g :: F (a->b)
fmap ($) :: F (a->b) -> F (a->b)
fmap ($) g :: F (a->b)
-- i.e.
fmap ($) g :: t -> (a->b)
首先,正如您所说,我们有
fmap :: Functor f
=> ( a -> b ) -> f a -> f b
($) :: (t->s) -> t -> s
g :: f a
~ f (t->s)
----------------------------------------- a ~ (t->s) ~ b
fmap ($) g :: f b
~ f (t->s)
然后将其应用于 x
... 但只有 函数 应用于参数:
fmap ($) g :: Functor f => f (t->s)
~ Functor ((->) c) => c -> (t->s)
x :: c
---------------------------------------------- f ~ ((->) c)
fmap ($) g x :: (t->s)
事实上 ((->) c)
是一个函子。因此,对 x
的应用是选择特定 Functor 类型,函数的 Functor。
综合起来,
-- g x
\g x -> fmap ($) g x :: (c -> (t->s)) -> c -> (t->s)
-- compare with
fmap ($) :: f (t->s) -> f (t->s) -- Functor (f ~ ((->) c)
fmap id :: f q -> f q
id :: r -> r
事实上,($)
只是一个更特殊的 id
和 fmap id === id
,根据 Functor Laws。由于所有额外的参数/实例化为其提供了更多上下文,该类型变得更加专业化。
我是 Haskell 的初学者。我知道函数 fmap
有两个参数 ((a->b) -> f a ->
) 和 returns 一个仿函数 (f b
),但我无法理解下面的 lambda 表达式
*Main> :t \g x -> fmap ($) g x
\g x -> fmap ($) g x :: (t -> a -> b) -> t -> a -> b
仿函数在哪里?
顺便说一句,我已经尝试了几个不同括号的相似表达式,它们给出了不同的结果:
*Main> :t \g x -> fmap ($) (g x)
\g x -> fmap ($) (g x) :: Functor f => (t -> f (a -> b)) -> t -> f (a -> b)
*Main> :t \g x -> fmap $ g x
\g x -> fmap $ g x :: Functor f => (t -> a -> b) -> t -> f a -> f b
我不明白这个。
来自
\g x -> fmap ($) g x :: (t -> a -> b) -> t -> a -> b
我们有
g :: t -> a -> b
x :: t
fmap ($) g :: t -> a -> b
fmap ($) g x :: a -> b
要找函子,写g
的类型作为类型级的应用F X
就可以了F
和X
.
我们有
t -> a -> b = (->) t (a -> b)
因此,F = (->) t
和 X = (a -> b)
。
因此,fmap
调用在 (->) t
函子中起作用。我们需要将 t -> a -> b
视为 a -> b
类型的值“包装”在函子 (->) t
.
现在,我们有
($) :: (a->b) -> a -> b
-- which means
($) :: (a->b) -> (a -> b)
g :: F (a->b)
fmap ($) :: F (a->b) -> F (a->b)
fmap ($) g :: F (a->b)
-- i.e.
fmap ($) g :: t -> (a->b)
首先,正如您所说,我们有
fmap :: Functor f
=> ( a -> b ) -> f a -> f b
($) :: (t->s) -> t -> s
g :: f a
~ f (t->s)
----------------------------------------- a ~ (t->s) ~ b
fmap ($) g :: f b
~ f (t->s)
然后将其应用于 x
... 但只有 函数 应用于参数:
fmap ($) g :: Functor f => f (t->s)
~ Functor ((->) c) => c -> (t->s)
x :: c
---------------------------------------------- f ~ ((->) c)
fmap ($) g x :: (t->s)
事实上 ((->) c)
是一个函子。因此,对 x
的应用是选择特定 Functor 类型,函数的 Functor。
综合起来,
-- g x
\g x -> fmap ($) g x :: (c -> (t->s)) -> c -> (t->s)
-- compare with
fmap ($) :: f (t->s) -> f (t->s) -- Functor (f ~ ((->) c)
fmap id :: f q -> f q
id :: r -> r
事实上,($)
只是一个更特殊的 id
和 fmap id === id
,根据 Functor Laws。由于所有额外的参数/实例化为其提供了更多上下文,该类型变得更加专业化。