2014-10-01 2 views
13

Я недавно занимался F # (мой фон - C#), и я читаю сайт http://fsharpforfunandprofit.com, который я нахожу очень полезным.(Kestrel) K-combinator: зачем это полезно?

У меня есть http://fsharpforfunandprofit.com/posts/defining-functions/, который является разделом комбинаторов. Я понимаю их всех (хотя комбинатор Y или птица Sage закручивают мой разум!), За исключением пустельги. Скотт Wlaschin дает определение (в F #) как:

let K x y = x 

Я не могу понять, за жизнь мне любой ситуации, в которой это было бы полезно. Сначала я думал, что он может использоваться как оператор цепи, так что вы можете передать значение функции, а затем вернуть исходное значение. Я написал такой оператор сам раньше, но, как вы можете видеть, что это не то же самое:

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

Если мы частично применим K комбинатор (со значением 5), то мы получим обратно функцию, которая игнорирует свой аргумент и вместо этого возвращается 5. Опять же, не полезно.

(K 5) = fun y -> 5 

Может ли кто-нибудь дать мне простой пример того, где это возможно использовать?

+1

: D Посмотрите на это: https://en.wikipedia.org/wiki/SKI_combinator_calculus - это действительно просто академическая забава - даже если вы найдете некоторые виды использования в F #, вы не должны называть его просто 'K' ^^ – Carsten

+1

BTW, если вы не нашли его сразу - 'K', например, используется для реализации таких вещей, как boolean, кортежи, числа, ... в SKI calculuse (ну это основной строительный блок;)) - просто подумайте это как вид проекции на первый компонент * – Carsten

+0

Спасибо, я прочитал страницу в Википедии, но он не дал больше информации, чем я уже имел. – Richiban

ответ

14

Вот очень простой пример:

Давайте предположим, что у меня есть структура, как список, где я могу карту функций.

let K x y = x 

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

Я могу сопоставить математические функции, как это:

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] 

Что делать, если я хочу, чтобы отобразить постоянную функцию?

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

Учитывая, что в FP вы обычно передавать функции в качестве аргументов, то K комбинатор позволяет задать постоянную функцию с помощью нескольких нажатий клавиш.

+0

Спасибо Gustavo, что тоже случилось со мной, это время, когда я тоже буду использовать 'id' (например,' lst |> sortBy id'), но все еще не получал точку постоянной функции на карте , Эквивалентный SQL будет «выбирать 5 из dbo.Customers'. Может быть, я буду продолжать думать. – Richiban

+0

Да, это эквивалент в SQL, но в FP вы можете создавать функции таким образом, чтобы вы могли отделить логику оценщика правил и правила. Подумайте о правилах как о функциях, и у вас может быть простое правило, для которого не требуется дополнительный параметр. Время от времени я использую комбинатор K в таких случаях, чтобы избежать повторения собственного написания «fun x -> something'' – Gustavo

+0

, в то время как true и хороший пример в реальной ситуации, вы, конечно же, будете использовать гораздо более читаемый« Список .replicate 4 10' (или '10 |> List.replicate 4') – Carsten

Смежные вопросы