F# 如何用任意数量的参数约束函数的返回类型?
我想创建一个带有类型注释的记录类型,约束条件是注释必须是返回特定类型的函数。考虑下面的例子: 输入Foo int>={ 函数:'Input->int } 类型ReturnsInt=FSharpFunc={ 函数:'ArgumentTuples->int } {Function=fun a,b,c,d,e,f,g->2}// {Function=fun a->2}//有效 {Function=fun a->}//不起作用F# 如何用任意数量的参数约束函数的返回类型?,f#,F#,我想创建一个带有类型注释的记录类型,约束条件是注释必须是返回特定类型的函数。考虑下面的例子: 输入Foo int>={ 函数:'Input->int } 类型ReturnsInt=FSharpFunc={ 函数:'ArgumentTuples->int } {Function=fun a,b,c,d,e,f,g->2}// {Function=fun a->2}//有效 {Function=fun a->}//不起作用 虽然这种方法有其自身的问题,并且不是原始问题的具体答案,但这种变通方法/工作
虽然这种方法有其自身的问题,并且不是原始问题的具体答案,但这种变通方法/工作流调整对我来说可能就足够了。我将把这个问题留待讨论。无论如何,我不能把这个评论标记为答案。这样的东西可能适合你,尽管你应该小心不要失去总体印象。如果数据模型非常复杂,分支可能会爆炸
module FunctionTests
//define function types templates
type F1<'a> = 'a -> int
type F2<'a, 'b> = 'a -> 'b -> int
type F3<'a, 'b, 'c> = 'a -> 'b -> 'c -> int
type F4<'a, 'b, 'c, 'd> = 'a -> 'b -> 'c -> 'd -> int
//define actual functions
let f1 : F1<string> = fun x ->
printf "calling f1: %s\n" x
1
let f2 : F2<string, string> = fun x y ->
printf "calling f2: %s; %s\n" x y
2
let f3 : F3<string, string, int> = fun x y z ->
printf "calling f2: %s; %s; %d\n" x y z
3
let f4 : F4<string, string, int, int> = fun x y z v ->
printf "calling f2: %s; %s; %d; %d\n" x y z v
4
//define DU limiting to a subset of functions
type FunctionChooser =
| FF1 of F1<string>
| FF2 of F2<string, string>
| FF3 of F3<string, string, int>
| FF4 of F4<string, string, int, int>
//define a record with the DU
type FunctionRec = {Function : FunctionChooser}
//testing harness
let callFunction (functiondefs : FunctionRec) data otherdata intparam1 intparam2 =
match functiondefs.Function with
| FF1 fn -> fn data
| FF2 fn -> fn data otherdata
| FF3 fn -> fn data otherdata intparam1
| FF4 fn -> fn data otherdata intparam1 intparam2
//tests
let res1 = callFunction {Function=FF1 f1} "somedata" "otherdata" 13 14
let res2 = callFunction {Function=FF2 f2} "somedata" "otherdata" 13 14
let res3 = callFunction {Function=FF3 f3} "somedata" "otherdata" 13 14
let res4 = callFunction {Function=FF4 f4} "somedata" "otherdata" 13 14
也许我在这里遗漏了一些东西,但为什么不简单地将您的类型定义为:
type Foo<'InputType> = {
Function: ('InputType -> int)
}
或更通用:
type Foo<'InputType, 'OutputType> = {
Function: ('InputType -> 'OutputType)
}
编辑:好的,我看到问题了。
因此,要使用Fyodors溶液,请执行以下操作:
type Foo<'InputType> = {
Function: ('InputType -> int)
}
let add a b = a + b
let myFunction = {
Function = (fun (a,b) -> add a b)
}
你为什么需要这个?我的意思是,在你达到这个目标后,你打算如何使用这种类型?不需要太深入的细节,大量的思考。我使用JSON源中的JToken压缩函数的任意数量的输入类型,将令牌转换为输入类型,然后使用正确类型的参数调用函数。为了更安全,我希望将所有这些限制为仅可用于返回特定类型的函数,该类型必须以特定的方式构造。考虑到最终目标,我建议将参数设置为元组而不是curry。这样,您的反射代码可以识别元组类型并使用正确类型的参数初始化它。这可能是目前为止最好的方法,谢谢。但是,它增加了将输入元组展平的复杂性。这只适用于具有一个输入参数的函数,正如我在问题的最后一个代码块中尝试显示的那样。Duh!好的,那么我建议Fyodors解决方案(如果适用)。
type Foo<'InputType, 'OutputType> = {
Function: ('InputType -> 'OutputType)
}
type Foo<'InputType> = {
Function: ('InputType -> int)
}
let add a b = a + b
let myFunction = {
Function = (fun (a,b) -> add a b)
}