在OCaml中,它是合法的,在.mli
:η膨脹在純函數式語言
val f : 'a -> 'a
val g : 'a -> 'a
和.ml
:
let f x = x
let g = f
在F#
然而,這個被拒絕:
eta_expand.ml(2,5): error FS0034: Module 'Eta_expand' contains
val g : ('a -> 'a)
but its signature specifies
val g : 'a -> 'a
The arities in the signature and implementation differ. The signature specifies that 'g' is function definition or lambda expression accepting at least 1 argument(s), but the implementation is a computed function value. To declare that a computed function value is a permitted implementation simply parenthesize its type in the signature, e.g.
val g: int -> (int -> int)
instead of
val g: int -> int -> int.
一種解決方法是η擴展g的定義:
let g x = f x
如果我的代碼是純功能性的(無異常,無副作用等),這應該是相等的(實際上,它可能是更好的針對多態,這取決於語言如何概括類型:OCaml中部分應用程序不會產生多態函數,但它們的η擴展會)。
系統η擴張有什麼缺點嗎?
兩個答案迴避了關於η-擴展的問題:-)而是建議我在我的功能類型周圍添加括號。這是因爲顯然,F#在功能的「真實」定義(如λ表達式和計算定義,如在部分應用程序中)之間的打字級別上區分開來;大概這是因爲λ表達式直接映射到CLR函數,而計算的定義映射到委託對象。 (我不知道這樣的解釋,如果有人非常熟悉F#可能指向參考文件描述此將不勝感激。)
一個解決方案是將括號中.mli
系統添加到所有功能類型,但我擔心這可能會導致效率低下。另一種方法是檢測計算的函數,並在.mli
中添加相應類型的括號。第三種解決方案是η擴展明顯的情況,並將其他表達爲括號。
我對F#/ CLR內部構件不夠熟悉,無法測量哪些測試會導致顯着的性能或接口處罰。
只要使它成爲'val g:('a - >'a)'。這是F#類型系統的已知功能/錯誤。 – 2013-04-05 09:03:27
再一次,「只是做它」 - 大概如果λ表達式和計算函數不具有可互換類型,這是有原因的。此外,這是自動生成的代碼,因此,這個問題比手動添加一些括號稍微複雜一些... – 2013-04-05 09:26:03
在這種情況下,兩者之間存在差異,一個編譯成一個方法,另一個編譯成靜態'功能'財產。兼容性不是雙向的(即「a→b:<: (a -> b」),而不是「(a→b):<: a -> b」)。 –
2013-04-05 10:41:14