Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# Can';t在F中创建函数的通用部分应用程序#_F# - Fatal编程技术网

F# Can';t在F中创建函数的通用部分应用程序#

F# Can';t在F中创建函数的通用部分应用程序#,f#,F#,我正在寻找一种方法来解决这种非常确定的情况:我有一个函数工厂toF,它接受一个函数参数g,并基于它创建一个结果函数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 mak

我正在寻找一种方法来解决这种非常确定的情况:我有一个函数工厂
toF
,它接受一个函数参数
g
,并基于它创建一个结果函数
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
保留在闭包中,只需要一个调用

更新(适用于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
更新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()

您只需将
f
设置为一个语法函数:

let toF g = 
    let f x = g x
    f
let f x = toF id x
f
在语法上不是一个函数(获取参数)而是一个值时,您会遇到“值限制”错误。我不打算在这里解释,因为在以前的帖子中已经有很多信息,比如:

编辑-如果要确保只调用一次
g
(但仍希望代码是通用的),最简单的方法是添加未使用的
unit
参数(使其成为函数),然后调用一次(确定通用参数)并多次使用结果:

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

let fg = f ()
fg 1
fg 2

这是非常必要的,因为拥有一个泛型函数,但通过某些计算返回,实际上会在类型系统中创建一个微妙的漏洞——这就是“值限制”的原因。

最简单的解决方案就是只添加一个类型注释。假设您只关心一种真正的类型,这是非常简单的:

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

类型FI不知道它是如何工作的:
让f x=toF id x
不应该工作,因为
toF id x
中有两个参数,而声明的
toF
只获取一个参数
g
。我的意思是x只是被忽略了还是什么?
let f x=
定义了一个函数(恰好返回了带另一个参数的函数),而
let f=
定义了一个值(实际上是一个带两个参数的函数),这实际上只是一个简单的语法条件-它必须是一个函数(至少带一些参数)Tomas,您建议的方法也不起作用(只要我们希望
fg
是通用的),您的示例只起作用,因为您在使用数字定义后立即调用
fg
,因此F#推断
fg
对数字进行操作,如果您删除
fg 1
fg 2
,您将得到相同的错误。。。函数似乎不是F#中的一等公民,因为它不能被返回并赋值。@AlekseyBykov你从哪里得到这个想法的?当然,你可以给一个值赋值,这就是你一直在做的事情,这就是F#的全部本质。