2017-04-08 40 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

相關問題