Обертка функции с неопределенным количеством параметров в F#

Я пытаюсь написать простой класс-оболочку на F#, который принимает функцию, возвращающую строку, и возвращает функцию, которая принимает те же параметры и возвращает строку из «завернутого» ввода.

Следующий код работает для функций, которые принимают одну переменную (поэтому test работает нормально):

open System

let myFunc anotherFunc =
    fun x -> "boo" + anotherFunc x + "unboo"

let Func2 toDouble =
    (toDouble * 2).ToString ()

let test = myFunc Func2

let Func3 numOne numTwo =
    (numOne * numTwo).ToString ()

let test2 = myFunc Func3

do
    Console.WriteLine(test 10)
    Console.WriteLine(test2 5 10)

Но поскольку fun x -> указывает один параметр, test2 не является допустимым кодом. Есть ли часть синтаксиса, которая позволила бы использовать эту конструкцию?


person mavnn    schedule 04.12.2011    source источник


Ответы (2)


Ваша функция работает. Проблема в вашей последней строке, когда вы делаете

let test2 = myFunc Func3

должно быть

let test2 x = myFunc (Func3 x)

ОБНОВИТЬ:

Я предполагаю, что вы не хотите менять Func3. В противном случае решение от Томаса может быть тем, что вам нужно.

person Gus    schedule 04.12.2011
comment
Это тоже сработает, но немного иначе, чем при обертывании функции, которая принимает только один параметр (или кортеж). В вашей версии функция myFunc выполняется каждый раз, когда вы вызываете test2, а в версии с одним параметром функция myFunc вызывается только один раз. В данном случае это не имеет особого значения, но если myFunc действительно что-то сделал, то это может быть проблемой — т. е. это может быть неэффективно или может не работать, если myFunc использовал какое-то внутреннее изменяемое состояние. - person Tomas Petricek; 05.12.2011
comment
Конечно, это зависит от вашего предположения. У меня нет полного исходного кода, поэтому я предположил, что вы не можете изменить Func3. - person Gus; 05.12.2011
comment
Я буду иметь предупреждение в виду. myFunc будет довольно легкой чистой функцией; снижение производительности для меня менее важно, чем возможность легкого каррирования функций, возвращаемых myFunc, поэтому решение Густаво лучше подходит для моего варианта использования. - person mavnn; 05.12.2011

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

// Function takeing a single argument, which is a tuple
let Func3 (numOne, numTwo) = 
  (numOne * numTwo).ToString () 

let test2 = myFunc Func3      

// The created function takes a tuple as well
Console.WriteLine(test2(5, 10))

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

person Tomas Petricek    schedule 04.12.2011