Неявный стиль программирования с использованием F#

Это не имеет практического значения, но я хотел бы увидеть пример неявного программирования в F#, где мои бесточечные функции могут иметь несколько аргументов (не в виде списка или кортежа).

И, во-вторых, как такие функции могут манипулировать сложной структурой данных. Я пробую это в F # Interactive, но пока безуспешно.

Я пробовал, например:

> (fun _ -> (fun _ -> (+))) 333 222 111 555

Это правильный путь?

И:

> (fun _ -> (fun _ -> (+))) "a" "b" "c" "d";;  

val it : string = "cd"

person Bubba88    schedule 08.05.2010    source источник
comment
Вы должны использовать точечный, а не бессмысленный. Это стандартный термин. :)   -  person Gregory Higley    schedule 04.06.2010


Ответы (2)


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

Однако вы можете определить несколько основных комбинаторов следующим образом:

// turns curried function into non-curried function and back
let curry f (a, b) = f a b
let uncurry f a b = f (a, b)

// applies the function to the first/second element of a tuple
let first f (a, b) = (f a, b)
let second f (a, b) = (a, f b)

Теперь вы можете реализовать функцию для сложения длин двух строк с помощью комбинаторов следующим образом:

let addLengths = 
  uncurry (( (first String.length) >> (second String.length) ) >> (curry (+)))

Это создает две функции, которые применяют String.length к первому/второму элементу кортежа, затем составляют их, а затем добавляют элементы кортежа, используя +. Все это обернуто в uncurry, так что вы получите функцию типа string -> string -> int.

person Tomas Petricek    schedule 08.05.2010
comment
Я проверил это в FSI, и это действительно работает! Большое Вам спасибо; Кстати, не могли бы вы объяснить, как вы пришли к синтаксису композиции функций кортежа? Я имею в виду (first String.length) >> (second String.length) Мне это кажется несколько необычным ;) - person Bubba88; 08.05.2010
comment
Это достигается с помощью функциональной композиции >>. Например, f >> g означает, что для аргумента x будет вызываться g(f(x)). В приведенном выше случае первая функция (first String.length) превращает кортеж string * string в кортеж int * string, а вторая функция (second String.length) превращает его в int * int, содержащий длины. - person Tomas Petricek; 08.05.2010
comment
Вы практически реализуете стрелки для F# ;) Хорошо, почему бы и нет — стрелки были изобретены как комбинация монад и неявного программирования. - person Dario; 10.08.2010

В F# арность функций фиксирована, поэтому вы не сможете написать обе функции одновременно.

(op) 1 2

и

(op) 1 2 3 4

для любого заданного оператора op. Вам нужно будет использовать список или другую структуру данных, если это то, что вы хотите. Если вы просто пытаетесь избежать именованных переменных, вы всегда можете сделать «1 + 2 + 3 + 4». Самый идиоматический способ добавить список чисел в F# — это List.sum [1;2;3;4], который также позволяет избежать использования переменных.

person kvb    schedule 08.05.2010