1

I want to use numeric literals in code quotations.

Following the two contributions

Function templates in F#

How to write a function for generic numbers?

one approach is:

type FromInt = FromInt with
    static member ($) (FromInt, _:sbyte     ) = fun (x:int) -> sbyte      x
    static member ($) (FromInt, _:int16     ) = fun (x:int) -> int16      x
    static member ($) (FromInt, _:int32     ) = id
    static member ($) (FromInt, _:float     ) = fun (x:int) -> float      x
    static member ($) (FromInt, _:float32   ) = fun (x:int) -> float32    x
    static member ($) (FromInt, _:int64     ) = fun (x:int) -> int64      x
    static member ($) (FromInt, _:nativeint ) = fun (x:int) -> nativeint  x
    static member ($) (FromInt, _:byte      ) = fun (x:int) -> byte       x
    static member ($) (FromInt, _:uint16    ) = fun (x:int) -> uint16     x
    static member ($) (FromInt, _:char      ) = fun (x:int) -> char       x
    static member ($) (FromInt, _:uint32    ) = fun (x:int) -> uint32     x
    static member ($) (FromInt, _:uint64    ) = fun (x:int) -> uint64     x
    static member ($) (FromInt, _:unativeint) = fun (x:int) -> unativeint x
    static member ($) (FromInt, _:bigint    ) = fun (x:int) -> bigint     x
    static member ($) (FromInt, _:decimal   ) = fun (x:int) -> decimal    x
    static member ($) (FromInt, _:Complex   ) = fun (x:int) -> Complex(float x,0.0)  

let inline fromInt (a:int) : ^t = (FromInt $ Unchecked.defaultof< ^t>) a

module NumericLiteralG =
    [<ReflectedDefinition>]
    let inline FromZero() = LanguagePrimitives.GenericZero
    [<ReflectedDefinition>]
    let inline FromOne() = LanguagePrimitives.GenericOne
    [<ReflectedDefinition>]
    let inline FromInt32 (i:int) = fromInt i

Adding [ < ReflectedDefinition > ] attribute to each of the ($) operators is fine. But once I add [ < ReflectedDefinition > ] to

let inline fromInt (a:int) : ^t = (FromInt $ Unchecked.defaultof< ^t>) a

I get the following compile error:

"Quotations cannot contain expressions that make member constraint calls, or uses of operators that implicitly resolve to a member constraint call"

Is this a limitation of quotations? Is there an alternative approach to get the same?

Many thanks for any idea.

Community
  • 1
  • 1
Daniel
  • 1,522
  • 1
  • 12
  • 25

1 Answers1

4

Quotations are limited in a number of ways. For example, they cannot contain generic functions, meaning that the following does not work:

<@ let id a = a in (id 3, id "A") @>

It should not be too surprising that they cannot handle functions with static member constraints like your fromInt function.

However, I do not quite understand why you want to be able to obtain the quotation of fromInt?

  • Normally, quotations are used to get the AST of some F# code and translate it to some other form (like SQL query, JavaScript or GPU code). This means that you'll be writing some function that recursively walks over the AST, translates the code and handles primitives in some special way.

If you do not mark fromInt as inline and ReflectedDefinition then you can just handle this single function as a primitive. (On the other hand, if it was inlined, you'd have to handle the FromInt.($) operator.

  • Alternatively, you may be transforming the quotation and then compiling it, but in this case, you should be just able to compile the quoted code containing a call to fromInt...

So, I'm curious what is the reason why you want to see the quotation of fromInt?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553