Functional programming 理解替换/`ap`类型签名和不同实现(函数式编程)时的混淆
我是函数式编程的学生,如果我的问题听起来很奇怪的话,我很抱歉——我正试着围绕函数的给定类型签名以及它们是如何实现的来思考 查看Functional programming 理解替换/`ap`类型签名和不同实现(函数式编程)时的混淆,functional-programming,ramda.js,category-theory,fantasyland,sanctuary,Functional Programming,Ramda.js,Category Theory,Fantasyland,Sanctuary,我是函数式编程的学生,如果我的问题听起来很奇怪的话,我很抱歉——我正试着围绕函数的给定类型签名以及它们是如何实现的来思考 查看ap(替换)的签名 (a)→ B→ (c)→ (一)→ (b)→ A.→ c 这里给出的是 consts=f=>g=>x=>f(x)(g(x)) 我想我能理解f是一个函数,它接受两个参数,a和b,并返回cg是一个函数,它接受a并返回b。因此g(a)返回b,因此f(a)(b)可以写成f(a)(g(a)),它返回c g(a)是b的替代品吗 好的,现在我正在研究另一个仍然有意
ap
(替换)的签名
(a)→ B→ (c)→ (一)→ (b)→ A.→ c
这里给出的是
consts=f=>g=>x=>f(x)(g(x))代码>
我想我能理解f
是一个函数,它接受两个参数,a
和b
,并返回c
g
是一个函数,它接受a
并返回b
。因此g(a)
返回b
,因此f(a)(b)
可以写成f(a)(g(a))
,它返回c
g(a)
是b
的替代品吗
好的,现在我正在研究另一个仍然有意义的实现:
ap(Identity(Math.sqrt)、Identity(64))
类型签名
(f(a->b),f a)->f b
似
(a)→ B→ (c)→ (一)→ (b)→ A.→ c
使用a=f、b=a和c=b重新写入第二个
(f->a->b)->(f->a)->f->b
假定ap
采用两个参数,其中,在第一个f
中可以是包含函数a->b
的某个函子,在第二个f
中,可以是包含a
的某个函子,返回一个函子,该函子将第一个函子的函数替换为端点b
,该函子包含a
好吧,退一步,这两件事看起来大不相同,我无法想象他们是如何说同样的话的
const S=f=>g=>x=>f(x)(g(x))
ap(Identity(Math.sqrt)、Identity(64))
根据我的理解,ap(F(g),F(a))
可以表示为F(a).map(g)
,同样,我仍然很难将其等同于const S=F=>g=>x=>F(x)(g(x))
。也许我误解了什么
…也许我的误解与ap
的表达有关,以及它与f=>g=>x=>f(x)(g(x))
的关系,因为我可以看到它们是如何表达相同的签名的,但我看不到它们是一样的
任何能在这里提供一些认知帮助的人,我都会非常感激它ap
是一个转换的名称,它在大量称为应用程序函子的容器类型上表现出相同的行为。函数就是这样一种容器类型:它可以被视为返回值的容器
你在我的要点中找到的S
组合符来自非类型的Lambda演算,是一个函数的变换。它恰好也是函数的Applicative Functor的一个有效实现,同时也是Ramda和saccession的首选实现。这就是为什么您可以将ap
用作S
为了了解ap
是如何成为S
,让我们看看ap
的签名:
Apply f=>(f(a->b),f a)->f b
让我们通过咖喱化函数来去掉逗号。这将使接下来的步骤更容易执行:
Apply f=>f(a->b)->f a->f b
Apply f
部分显示,无论我们在哪里看到fa
,我们都可以使用包含a
的Applicative Functor容器。让我们通过将f
替换为(函数x)
来专门为函数容器指定此签名x
是该函数的输入,接下来是输出
(功能x)(a->b)->(功能x)a->(功能x)b
这是这样的:给定从x
到a
到b
的函数,以及从x
到a
的函数,将函数从x
返回到b
由于构造函数关联性的工作方式,我们可以删除函数x
周围的括号:
函数x(a->b)->函数x a->函数x b
编写函数ab
的另一种方法是使用箭头符号:(a->b)
,因此在下一步中,我们只需这样做:
(x->(a->b))->(x->a)->(x->b)
最后,我们可以再次去掉额外的括号,并发现它是我们的组合符:
(x -> a -> b) -> (x -> a) -> x -> b
(a -> b -> c) -> (a -> b) -> a -> c
首先,我认为对于非类型lambda演算中函数类型的应用函子为什么被称为替换,没有简单的解释。AFAIK,Schönfinkel最初称这种组合融合或融合函数
为了专门化一般的应用函子类型(f(a->b),f a)->f b
(无载波形式),我们需要知道参数化类型变量f
在函数类型的上下文中准确表示什么
正如每个函子一样,应用函子是在单个类型上参数化的。然而,函数类型构造函数需要两种类型——一种用于参数,另一种用于返回值。为了使函数成为(应用程序)函子的实例,我们必须忽略返回值的类型。因此,f
表示(a->)
,即函数类型本身及其参数的类型。部分应用的函数类型构造函数的正确表示法实际上是前缀(>)a
,所以让我们坚持这一点
接下来,我将用curry格式重写通用应用程序类型,并用(>)r
替换f
。我用另一个字母给d
(f (a -> b), f a) -> f b
f (a -> b) -> f a -> f b // curried form
// substitution
(->) r (a -> b) -> (->) r a -> (->) r b // prefix notation
(r -> a -> b) -> (r -> a) -> (r -> b) // infix notation
// omit unnecessary parenthesis
(r -> a -> b) -> (r -> a) -> r -> b