f# - Static member constraint for op_addition -


i trying reinvent list.fold, list.reduce, , list.sum using pointfree inline functions sake of learning. here had:

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 0 : ^a) > :      (^a -> ^a -> ^a) -> ^a list -> ^a =     flip fold languageprimitives.genericzero  let inline sum< ^a when              ^a : (static member (+) : ^a * ^a -> ^a) ,              ^a : (static member 0 : ^a)> : ^a list -> ^a =      reduce (+)            // ^ compile error here 

i know such verbose type constraints not used in f# trying learn please bear me.

i got cryptic compile error not understand:

type mismatch. expecting     'a -> 'a -> 'a  given     'a -> 'b -> 'c      type parameter missing constraint 'when ( ^a or  ^?269978) : (static member ( + ) :  ^a *  ^?269978 ->  ^?269979)'  type parameter missing 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: first parameter.  y: second parameter. 

what should add satisfy compiler?

i don't know way of doing want, because there's no way know of invoke statically constrained static member in pointfree style. note not invoking (+) of ^a , compiler not know how figure out... if happy using inner helper function, can do:

let inline sum< ^a     when ^a : (static member (+) : ^a -> ^a -> ^a) ,          ^a : (static member 0 : ^a) > : ^a list -> ^a =     let add x y = (^a : (static member (+) : ^a -> ^a -> ^a) (x, y))     reduce add 

note warning

warning fs0077: member constraints name 'op_addition' given special status f# compiler .net types implicitly augmented member. may result in runtime failures if attempt invoke member constraint own code.

and indeed:

sum [1; 2; 3] leads to

system.notsupportedexception: specified method not supported.
     at fsi_0005.it@15-1.invoke(int32 x, int32 y) in ...

but if change sum to:

let inline sum list =     reduce (+) list  sum [1; 2; 3] // 6 

Comments