har*_*rms 7 f# haskell type-systems functional-programming language-design
在静态类型的函数式编程语言中,如标准ML,F#,OCaml和Haskell,函数通常用参数相互分离,并且只用空格从函数名中编写:
let add a b =
a + b
Run Code Online (Sandbox Code Playgroud)
这里的类型是" int -> (int -> int)
",即一个接受int的函数,返回一个转到的函数和int,最后返回一个int.因此,成为可能.
也可以定义一个以元组作为参数的类似函数:
let add(a, b) =
a + b
Run Code Online (Sandbox Code Playgroud)
(int * int) -> int
在这种情况下,类型变为" ".
从语言设计的角度来看,有没有理由不能简单地在类型代数中识别这两种类型模式?换句话说,使"(a*b) - > c"减少到"a - >(b - > c)",允许两种变体同样容易地变成曲线.
我认为当我提到的四种语言被设计出来时,这个问题肯定会出现.那么有谁知道任何理由或研究表明为什么所有这四种语言都选择不"统一"这两种类型模式?
我认为今天的共识是通过currying(形式)来处理多个参数,a -> b -> c
并在你真正想要元组类型的值时(在列表等中)保留元组.自标准ML以来,每个静态类型的函数语言都遵循这种共识,(纯粹作为惯例)将元组用于带有多个参数的函数.
为什么会这样?标准ML是这些语言中最古老的,当人们第一次编写ML编译器时,不知道如何有效地处理curried参数.(问题的根源在于,任何 curry函数都可以部分应用于您尚未看到的其他代码,并且您必须考虑到这种可能性进行编译.)自设计标准ML以来,编译器具有改进了,您可以在Simon Marlow和Simon Peyton Jones的优秀论文中了解最新技术.
LISP是它们中最古老的函数式语言,它具有一种具体的语法,对于currying和部分应用程序非常不友好.Hrmph.
可能是因为将元组作为单独的类型很有用,并且将不同的类型分开也很好?
至少在 Haskell 中,从一种形式转变为另一种形式是相当容易的:
Prelude> let add1 a b = a+b
Prelude> let add2 (a,b) = a+b
Prelude> :t (uncurry add1)
(uncurry add1) :: (Num a) => (a, a) -> a
Prelude> :t (curry add2)
(curry add2) :: (Num a) => a -> a -> a
Run Code Online (Sandbox Code Playgroud)
所以uncurry add1
与 相同add2
且curry add2
与 相同add1
。我想类似的事情在其他语言中也是可能的。自动柯里化元组上定义的每个函数会有什么更大的好处?(因为这似乎就是你想问的。)
归档时间: |
|
查看次数: |
778 次 |
最近记录: |