F# 我是否可以对curried函数应用运算符,使其返回类型为unit,而不指定参数的数量?
给定一个具有任意参数类型和数字的任意函数F# 我是否可以对curried函数应用运算符,使其返回类型为unit,而不指定参数的数量?,f#,F#,给定一个具有任意参数类型和数字的任意函数func,我想得到一个返回单位--func,返回值被忽略的函数。将其视为对纯粹副作用函数的投影。如果func接受一个参数(或者如果它是无载波形式),那么它就是func>>忽略。显而易见的解决方案是为我们需要的func的每个参数编写一个泛型运算符: let inline unitise1 f a = f a |> ignore let inline unitise2 f a b = f a b |> ignore let inline uniti
func
,我想得到一个返回单位--func
,返回值被忽略的函数。将其视为对纯粹副作用函数的投影。如果func
接受一个参数(或者如果它是无载波形式),那么它就是func>>忽略。显而易见的解决方案是为我们需要的func
的每个参数编写一个泛型运算符:
let inline unitise1 f a = f a |> ignore
let inline unitise2 f a b = f a b |> ignore
let inline unitise3 f a b c = f a b c |> ignore
let inline unitise4 f a b c d = f a b c d |> ignore
这是混乱和不方便的,因为我们每次都需要计算参数,而且代码不会很好地重构。是否有一种语言结构是我所缺少的,可以让我做这件事
编辑:我相信这样一个操作符会很有用,因为NET
泛型比F#
静态解析类型参数弱。这就是我的意思。假设我有一个高阶函数
let inline higher f g =
f 7 |> ignore
g 3 |> ignore
我们可以向它传递任何函数,只要它的第一个参数是int
。因此,这将起作用:
let add n = n+1
let str (n:int) = n.ToString()
higher add str
higher str add
特别是,不需要泛型类型注释。这就是我们对F#的了解和热爱。现在,我遇到了一种情况,我需要传递大量(~15)个函数作为更高版本的参数。它们将在调用链中传递多次。在数据结构中对它们进行分组是很自然的
type Funcs<'R1,'R2,'R3> = {f1:int->'R1;f2:int->'R2;f3:int->'R3}
并将使用一个辅助函数,在从它们构建Funcs
之前将每个函数统一起来。在这个玩具示例中,f
和g
都有一个参数,因此解决方案很简单,但在实际情况中,不同的函数有不同数量的参数
写了这些问题后,我咬紧牙关,写了一大堆带有15个泛型参数的Funcs
。@TomasPetricek是绝对正确的,你不能构建这样的函数这是证据。
假设,您已创建了unitise
函数,以便以下各项正常工作:
// just sample functions with 1, 2, and 3 curried arguments
let f1 a = a
let f2 a b = (a,b)
let f3 a b c = (a,b,c)
let x1 = unitise f1 5 // expected x1:unit
let x2 = unitise f2 5 42 // expected x2:unit
let x3 = unitise f3 5 "foobar" 42 // expected x3:unit
对于任意数量的curried参数没有泛型,因此在调用unitise
之前,必须计算(f1 5)
、(f2 5 42)
等:
let x1 = unitise (f1 5) // expected x1:unit
let x2 = unitise (f2 5 42) // expected x2:unit
let x3 = unitise (f3 5 "foobar" 42) // expected x3:unit
因此,unitise
相当于ignore
:
let x3 = ignore (f3 5 "foobar" 42) // expected x3:unit
如果您希望<代码>忽略< /代码>(或<代码> Untudio)放置在语句的开头,也避免括号用于可读性的目的,请考虑使用<强>高优先级、右关联向后管、<代码>(^这类函数的定义是不连贯的。请记住,在f#中,没有一个函数的参数超过1个
功能
let f a b = 0
与
let f a = fun b -> 0
所以应该是这样
unitize f a b = ()
及
这意味着
() b = ()
我不知道我是否理解你为什么要这样做。即使你有这样的功能,比如说unitise
,当你调用该函数时,使用它仍然需要与使用ignore
相同的工作量……或者你是否考虑了其他用例?@TomasPetricek我已经添加了一些细节。谢谢。我意识到这是不可能的使用高阶函数。这就是为什么我问一些我可能缺少的语言结构。一个例子可能是一个符号,它捕获所有curry参数,并允许它们在以后应用。
let f a = fun b -> 0
unitize f a b = ()
unitize f a = ()
() b = ()