2011-03-26 21 views
9

Örneğin, here açıklandığı gibi, F # içindeki fonksiyon kompozisyonunun temellerini anlarım.Neyi eksik: Birden fazla argümanı olan fonksiyon kompozisyonu mümkün mü?

Belki de bir şeyleri özlüyorum. >> ve << operatörleri her fonksiyon sadece bir argüman alır varsayımıyla tanımlanmıştır görünmektedir:

let add a b = a + b 
let double c = 2*c 
let addAndDouble = add >> double // bad! 
:

> (>>);; 
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) = <fun:[email protected]> 
> (<<);; 
val it : (('a -> 'b) -> ('c -> 'a) -> 'c -> 'b) = <fun:[email protected]> 

ben yapmak istiyorum Ne Ancak, aşağıdaki gibi bir şey

Ancak add'un çıkışı, double'un girişi için gerekli olsa da, bu reddedilir.

let add (a,b) = a + b 

Ya ben ilk işleve olası argümanlar her sayısı için yeni bir operatöre yazabilirsiniz:

let inline (>>+) f g x y = g (f x y) 
let doubleAdd = add >>+ double 

Ama bunu

ben bir tanımlama grubu argümanı ile ekleyebilir yeniden yazabilirsiniz biliyoruz aptalca görünüyor! Kaçırdığım daha iyi bir yolu var mı?

cevap

11

İstediğiniz şey tamamen mantıksız değildir, ancak F # türü içinde genelleştirilmiş kompozisyon operatörünün türünü belirtmenin bir yolu yoktur. sistemi. Yani

(>>) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c 

ve

(>>+) : ('a -> 'b -> 'c) -> ('c -> 'd) -> 'a -> 'b -> 'd 

(sonsuz sayıda yüksek Arity versiyonlarını saymıyorum) birleştirmeye için iyi bir yol yok demek. Bu nedenle, kendi ek işleçlerinizi tanımlamaktan başka seçeneğiniz yoktur. Pratikte, çoğunlukla "sivri" stilinde let f x y = add x y |> double 'da daha önce okunabilir/"anlamsız" let f = add (>>+) double'dan daha okunabilir kodlar yazdım.

+1

Anlaştık, sivri tarzı genellikle daha okunabilir. – Laurent

+2

Özellikle, fonksiyonlarınızı 'çevirmeye' başladığınızda. –

4

Yukarıda gönderdiğiniz >> ve << türlerine bakın. örneğin:

> (>>);; 
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) = <fun:[email protected]> 

Bu iki işlevi ve bir değer ('a) alır ve başka bir değer döndürür. İki işlevi ve 2 değeri alan bir şeye ihtiyacınız var. Bu nedenle, her ikisi de >> ve << doğru tür imzası yok.

Uygulamanız hiç de aptalca değil. Sadece ihtiyacın F # 'ın kütüphanelerindeki kutudan çıkmıyor. Kendi işleçlerinizi bu şekilde tanımlamanıza izin veren bir dile sahip olduğunuz için minnettar olun :)

3

Bir yığın argümanı işleyerek nasıl yapılır?

let doubleAdd = add >> double 

Ve çalışır::

let add = function x :: y :: t -> x + y :: t 
let double = function x :: t -> 2 * x :: t 

Sonra keyfi Arity işlevlerini oluşturabilirsiniz

> doubleAdd [7; 14] 
42 

(bkz ayrıca F# Function Composition with multiple input parameters)

İlgili konular