2014-10-01 26 views
13

Recentemente ho assunto F # (il mio background è C#) e sto leggendo il sito http://fsharpforfunandprofit.com, che sto trovando molto utile.(Kestrel) K-combinator: perché è utile?

Devo http://fsharpforfunandprofit.com/posts/defining-functions/ che è la sezione sui combinatori. Li capisco tutti (anche se il combinatore Y o Sage si avvita con la mente!) Con l'eccezione del Gheppio. Scott Wlaschin dà la definizione (in F #) come:

let K x y = x 

non riesco a capire per la vita di me qualsiasi situazione in cui questo sarebbe utile. All'inizio ho pensato che potesse essere usato come operatore di catena, in modo da poter passare un valore a una funzione e quindi recuperare il valore originale. Ho scritto un tale operatore me stesso prima, ma come si può vedere che non è lo stesso:

let (>|) x f = f x; x 

Se parzialmente applichiamo il combinatore K (con il valore 5) allora torniamo una funzione che ignora il suo argomento e invece restituisce 5. Ancora, non utile.

(K 5) = fun y -> 5 

Qualcuno può darmi un esempio semplice di dove questo potrebbe essere utilizzato per favore?

+1

: D dai un'occhiata a questo: https://en.wikipedia.org/wiki/SKI_combinator_calculus - è davvero divertente da un punto di vista accademico - anche se trovi alcuni usi in F # non dovresti chiamarlo solo "K" ^^ – Carsten

+1

BTW se non lo trovi subito - 'K' è ad esempio usato per implementare cose come booleani, tuple, numeri, ... nel calcolo SCI (beh è un elementare elementare;)) - pensa a è una sorta di proiezione del * primo componente * – Carsten

+0

Grazie, ho letto la pagina di Wikipedia ma non ho dato più informazioni di quante ne avessi già. – Richiban

risposta

14

Ecco un esempio molto semplice:

Facciamo supponiamo di avere una struttura, come una lista in cui posso mappare le funzioni.

let K x y = x 

let lst = [3;5;13;2] 

Posso tracciare funzioni matematiche come questo:

let plus5 = lst |> List.map ((+)5) // instead of writing List.map (fun x -> 5 + x) 
// val plus5 : int list = [8; 10; 18; 7] 

let times3 = lst |> List.map ((*)3) // instead of writing List.map (fun x -> 3 * x) 
// val times3 : int list = [9; 15; 39; 6] 

Cosa devo fare per mappare una funzione costante?

let tens = lst |> List.map (K 10) // instead of writing List.map (fun x -> 10) 
// val tens : int list = [10; 10; 10; 10] 

dato che in FP in genere si passa funzioni come argomenti, il combinatore K consente di specificare una funzione costante con pochi tasti.

+0

Grazie Gustavo, anche a me è capitato, è come se usassi anche 'id' (come' lst |> sortBy id'), ma ancora non ottenevo il punto di una funzione costante in una mappa . L'equivalente SQL sarebbe 'selezionare 5 da dbo.Customers'. Forse continuerò a pensare. – Richiban

+0

Sì, è una specie di equivalente in SQL, ma in FP è possibile comporre le funzioni in modo tale da poter separare la logica di un analizzatore di regole e una regola. Considera le regole come funzioni e potresti avere una regola semplice che non richiede un parametro aggiuntivo. Uso il combinatore K di volta in volta in casi del genere per evitare di ripetere la mia auto-scrittura '' fun x -> something'' – Gustavo

+0

mentre vero e un bell'esempio nella situazione reale si userebbe ovviamente la 'Lista molto più leggibile .replicate 4 10' (o '10 |> List.replicare 4') – Carsten