2013-10-24 2 views
2

Я ищу способ исправить эту очень определенную ситуацию: у меня есть функция-фабрика toF, которая принимает функциональный параметр g и на его основе создает результирующую функцию fНевозможно создать общее частичное применение функции в F #

let toF g = 
    let f x = g x 
    f 
let f = toF id 

проблема заключается в том, что я получаю

error FS0030: Value restriction. The value 'f' has been inferred to have generic type val f : ('_a -> '_a) Either make the arguments to 'f' explicit or, if you do not intend for it to be generic, add a type annotation. 

Я могу добавить аннотацию типа (которые, я не готов сделать) или же я могу переписать так:

let f' g x = g x 
let f x = f' id x 

Я не люблю делать это таким образом, потому что, если я тогда каждый раз, когда я называю f я сделать еще один вызов f' с указанием g по пути. В то время как первый пример держит g в закрытии и требует только одного вызова.

UPDATE (для Tomas)

Я попробовал то, что вы предложили.

let toF g = 
    printfn "Creating f using g" 
    let f x = 
     printfn "x: %A" x 
     g x 
    f 
let f x = toF id x 

let ``test``() = 
    1 |> f |> f |> ignore 

Что в основном происходит в том, что каждый раз, когда я делаю вызов функции f это первые вызовы toF id получать составленную функцию и только затем вызывает функцию, которая состоит в x.

Creating f using g 
x: 1 
Creating f using g 
x: 1 

Таким образом, по существу, композиция создается на каждом вызове f через последующий вызов к toF. Но это именно то, чего я пытался избежать. Определив let f = toF id, я надеялся получить закрытие одного сиглея, а затем сразу же позвоню. Таким образом, выход я ожидал бы:

Creating f using g 
x: 1 
x: 1 

UPDATE 2

Следующая не работает либо по той же самой причине:

let toF g = 
    printfn "Creating f using g" 
    let f x = 
     printfn "x: %A" x 
     g x 
    f 
let f() = toF id 
let fg = f() 

ответ

6

Вам просто нужно сделать f синтаксическая функция:

let toF g = 
    let f x = g x 
    f 
let f x = toF id x 

Когда f не является синтаксически функцией (принимая параметр), но значением, вы попадаете в ошибку «ограничение значения». Я не собираюсь объяснять это здесь, потому что в предыдущих сообщениях есть очень хорошая информация: Understanding F# Value Restriction Errors.

EDIT - Если вы хотите, чтобы убедиться, что g вызывается только один раз (но все еще хотите, чтобы код был родовым), то самый простой способ добавить неиспользованный unit параметр (чтобы сделать его функции), а затем вызвать это один раз (который определяет общие параметры) и использовать результат несколько раз:

let toF g = 
    let f x = g x 
    f 
let f() = toF id 

let fg = f() 
fg 1 
fg 2 

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

+0

Я не понимаю, как это работает: 'let fx = toF id x' не должно работать, поскольку в' toF id x' есть 2 аргумента, тогда как объявленный 'toF' получает только один параметр' g'. Я имею в виду, что x просто игнорируется или что? –

+0

'let fx =' определяет функцию (которая возвращает функцию, принимающую другой аргумент), а 'let f =' определяет значение (которое фактически является функцией из двух аргументов) –

+0

Это действительно просто синтаксическое условие - оно имеет быть функцией (принимая хотя бы некоторый аргумент) –

1

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

let toF g = 
    let f x = g x 
    f 
let f : _ -> int = toF id 

Если вам действительно нужно позвонить f в различных типах, то вы можете обернуть его в универсальном типе:

type F<'t>() = 
    static member val f : _ -> 't = toF id 

let blah = F.f "blah" 
let one = F.f 1 
+0

Nice ... Кажется, что функция не является первоклассным гражданином в F #, поскольку она не может быть возвращена и присваивается значение. –

+0

@AlekseyBykov Где у вас такая идея? Конечно, вы можете назначить функцию значению, это то, что вы делаете все время, и это вся суть F #. – Abel

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