2017-04-08 37 views
3

在函数式编程中,调用不接受参数的函数的正确名称是什么?例如:调用具有空参数的函数的术语

// 2 types of execute functions 
type Function = 
    | UnitFunction of (unit -> unit) 
    | OperandFunction of (unit16 -> unit) 

let nop() = 
    () 

let shiftRegisterA operand = 
    registers.A <- registers.A <<< operand 

可以nop被称为UnitFunctionshiftRegisterA被称为OperandFunction

回答

9

你在这里指的是一般称为arity的一个函数。因此,没有参数的函数将被称为空函数和具有单一参数的函数 - 一元函数。

虽然您仍然可以在F#函数的上下文中使用这个术语,并且可以普遍理解,但这并不完全准确。 F#函数通常只接受一个参数并返回一个值,这是因为缺省情况下函数会被curry。

在你的情况,nop有类型unit -> unit。这意味着它需要一个类型为unit(该类型的唯一()值)的单个参数,并返回unit类型的结果。尽管如此,这仍然是一个单一的功能。

2

在汇编程序中调用一个函数是在堆栈上推送参数(或根据调用约定寄存器)然后跳转到函数地址的过程。

在更多高级语言中,例如Java,C#,C等等,这个过程或多或少都隐藏在我们的面前。但是,当我们调用不带参数的函数时,我们会看到它的痕迹,即void。在函数式编程语言(如F#,haskell等)中,函数的概念更接近于从单个输入产生答案的数学函数。

地看到,在F#的所有函数接受单个输入让我们来看看下面的函数:

// val f: (int*int) -> int 
let f (x,y) = x + y 

f接受一对整数,并产生一个整数。这两个人从f的角度来看,它解构了一个单一的价值来产生答案。

// val g: int -> int -> int 
let g x y = x + y 

显然,这似乎是一个接受两个整数从而产生一个整数的功能,但如果我们把它改写略有我们看到事实并非如此:

// val h: int -> int -> int 
let h x = fun y -> x + y 

h相当于g但在这里我们看到h实际上只接收一个整数,该整数产生一个接受整数来产生整数的函数。

签名中的->是正确的联想,我们添加了更多的偏见,我们更清楚地看到gh实际上只是一个输入。

// val g: int -> (int -> int) 
let g x y = x + y 

// val h: int -> (int -> int) 
let h x = fun y -> x + y 

let gx = g 1 2 
let gy = (g 1) 2 
let hx = h 1 2 
let hy = (h 1) 2 

在F#我看来,功能比功能的更高层次的抽象的说,C#/ Java作为C#/ Java的功能在概念上更接近比F#的功能是汇编语言的功能。另外,如果每个函数都需要一个参数,那么对于不接受参数的函数来说,这是没有意义的。

但是这个功能呢?

// val i: unit -> int 
let i() = 3 

它不接受没有参数产生3?不,它接受单位价值(),这只是unit类型中的价值。

在Haskell他们有一个名称,接受void,并产生一个答案功能:

absurd :: Void -> a 

值或许可以看作是不带参数的函数,但我不是一个范畴论专家。

再回到示例代码:

type Function = 
| UnitFunction of (unit -> unit) 
| OperandFunction of (unit16 -> unit) 

功能的方法将是这样的:

type Abstraction = 
| Concrete of obj 
| Function of Abstraction -> Abstraction 

Ie的Abstraction是一个值或一个函数。

看看代码,它似乎模仿了看起来接近汇编语言的东西,所以在这种情况下,可以将函数看作是推送参数并跳转到地址。

type Function = 
| VoidFunction of (unit -> unit) 
| UnaryFunction of (unit16 -> unit) 
| BinaryFunction of (unit16 -> unit16 -> unit) 

希望这很有趣。

PS。

看起来好像unit类型是一个小细节,但IMO使许多好东西。

  • 无需声明。
  • 简化通用编程(void案例通常需要特殊情况,考虑Task<'T>Task)。
  • 允许我们思考数学函数等功能,而不是跳转到内存中的地址。
+1

回复:特殊的'void'情况下,C#中最震撼的一个是'Action'和'Func'类型之间的分割。 – scrwtp

相关问题