为了学习,我尝试重新发明List.fold、List.reduce和List.sum,使用无点的inline函数。以下是我所拥有的:
let flip f y x = f x y
let rec fold folder seed = function
| [] -> seed
| h :: t -> fold folder (folder seed h) t
let inline reduce< ^a when ^a : (static member Zero : ^a) > :
(^a -> ^a -> ^a) -> ^a list -> ^a =
flip fold LanguagePrimitives.GenericZero
let inline sum< ^a when
^a : (static member (+) : ^a * ^a -> ^a) and
^a : (static member Zero : ^a)> : ^a list -> ^a =
reduce (+)
// ^ Compile error here我知道这种冗长的类型约束在F#中并不经常使用,但是我正在努力学习,所以请容忍我。
我收到了一个非常神秘的编译错误,我不明白:
Type mismatch. Expecting a
'a -> 'a -> 'a
but given a
'a -> 'b -> 'c
A type parameter is missing a constraint 'when ( ^a or ^?269978) : (static member ( + ) : ^a * ^?269978 -> ^?269979)'
A type parameter is missing a constraint 'when ( ^a or ^?269978) : (static member ( + ) : ^a * ^?269978 -> ^?269979)'
val ( + ) : x:'T1 -> y:'T2 -> 'T3 (requires member ( + ))
Full name: Microsoft.FSharp.Core.Operators.( + )
Overloaded addition operator
x: The first parameter.
y: The second parameter.我应该添加什么来满足编译器?
发布于 2016-08-01 16:17:34
我不知道一种完全按照您的要求执行的方法,因为我不知道如何以无切入点的方式调用静态约束的静态成员。请注意,您没有调用(+) of ^a,编译器也不知道如何解决这个问题.如果您乐于使用内部助手函数,则可以:
let inline sum< ^a
when ^a : (static member (+) : ^a -> ^a -> ^a) and
^a : (static member Zero : ^a) > : ^a list -> ^a =
let add x y = (^a : (static member (+) : ^a -> ^a -> ^a) (x, y))
reduce add注意警告
警告FS0077:名为“op_Addition”的成员约束由F#编译器给出特殊状态,因为某些.NET类型是通过该成员隐式增强的。如果尝试从自己的代码中调用成员约束,这可能导致运行时失败。
事实上:
sum [1; 2; 3]导致
System.NotSupportedException:不支持指定的方法。 .=‘Int32 1’>(Int32 x,Int32 y)在.
但是,如果将sum更改为:
let inline sum list =
reduce (+) list
sum [1; 2; 3] // 6发布于 2016-08-01 16:57:01
我无济于事的回答是:不要那样做。内联定义只用于语法功能,因此不应该以无点的方式定义它们。例如,比较尝试评估以下三行的结果:
let inline identity = id
let inline identity : ^a -> ^a = id
let inline identity< ^a> : ^a -> ^a = id只有最后一个函数进行编译(从技术上讲,这是因为它是一个“类型函数”,基本上是一个函数,它在幕后传递一个不可见的unit值,允许将其作为泛型值处理)。
但是,如果您坚持这样做,那么“修复”的一种方法就是降低(+)的泛型;默认情况下,参数和返回类型可以是不同的类型,这种灵活性带来的约束是使编译器感到困惑的部分原因。这里有一个解决办法:
let inline reduce< ^a, 'b when ^a : (static member Zero : ^a)> : ( ^a -> 'b -> ^a) -> ('b list -> ^a) =
flip fold LanguagePrimitives.GenericZero
let inline (+) (x:^a) (y:^a) = x + y
let inline sum< ^a
when ^a : (static member ( + ) : ^a * ^a -> ^a)
and ^a : (static member Zero : ^a)> : ^a list -> ^a =
reduce (+)发布于 2016-08-01 16:29:18
就像Vandroiy一样,给定的减值函数不会为我编译。我认为您想要的reduce函数实际上是:
let inline reduce< ^a when ^a : (static member Zero : ^a) > : ((^a -> ^a -> ^a) -> ^a list -> ^a) =
flip fold LanguagePrimitives.GenericZero这样我就能复制出你的错误了。
但是,当我通过使用简单的测试函数将sum函数更改为编译时:
let inline sum< ^a when
^a : (static member Zero : ^a) and
^a : (static member (+) : (^a -> ^a -> ^a)) > : ^a list -> ^a =
reduce (fun i j -> i)并试图在sum [1..10]中调用The type 'int' does not support the operator 'get_op_Addition'结果。所以我不确定这个方法会不会起作用。
编辑:谢谢CaringDev的提示,我修复了get_op_Addition错误。这似乎很管用。至于为什么,我很困惑,因为'b只是伪装的^a .
let inline sum< ^a when
^a : (static member Zero : ^a) and
^a : (static member (+) : ^a -> ^a -> ^a) > : ^a list -> ^a =
let inline add (x:'b) (y:'b) = (+) x y
reduce addhttps://stackoverflow.com/questions/38701715
复制相似问题