Skip to content

In quoted expressions or reflected definitions operators involved in constraints are not permitted although a named method with the same constraint is? #6344

@7sharp9

Description

@7sharp9

Please provide a succinct description of the issue.

Repro steps

Provide the steps required to reproduce the problem

In Falanx we consuming Fleece for record type like this, using combinators to form codecs for transforming to and from json types:

type NewSampleMessage =
    { mutable martId : int option
      mutable test_oneof : string option }
    
    static member JsonObjCodec =                
        fun m t -> {martId = m; test_oneof = t}
        <!> jopt "martId"  (fun b -> b.martId)
        <*> jopt "test_oneof" (fun a -> a.test_oneof)

With these definitions you are not allowed to add the reflected definition attribute:

    [<ReflectedDefinition>]
    static member JsonObjCodec =                
        fun m t -> {martId = m; test_oneof = t}
        <!> jopt "martId"  (fun b -> b.martId)
        <*> jopt "test_oneof" (fun a -> a.test_oneof)

Screen Shot 2019-03-20 at 13 09 53

But adding some extension methods that use exactly the same constraints works fine:

[<AutoOpen>]
module FleeceExtensions =
    open FSharpPlus
    open Fleece.Newtonsoft
    type ConcreteCodec<'S1, 'S2, 't1, 't2> with
        static member inline map  (field: ConcreteCodec<'S, 'S, 'f, 'T>) (f) =
            f <!> field
        
        static member inline apply  (currentField: ConcreteCodec<'S, 'S, 'f, 'T>) (remainderFields: ConcreteCodec<'S, 'S, 'f ->'r, 'T>) =
            remainderFields <*> currentField

type NewSampleMessage =
    { mutable martId : int option
      mutable test_oneof : string option }
    
    [<ReflectedDefinition>]
    static member JsonObjCodec =                        
        fun m t -> {martId = m; test_oneof = t}
        |> ConcreteCodec.map (jopt "martId"  (fun b -> b.martId))
        |> ConcreteCodec.apply (jopt "test_oneof" (fun a -> a.test_oneof))

The reflected definition can be easily extracted now:

Lambda (unitVar0,
        Call (None, op_PipeRight,
              [Call (None, op_PipeRight,
                     [Lambda (m, Lambda (t, NewRecord (NewSampleMessage, m, t))),
                      Application (Lambda (arg00,
                                           Lambda (arg10,
                                                   Call (None,
                                                         ConcreteCodec`4.map.Static,
                                                         [arg00, arg10]))),
                                   Call (None, jopt,
                                         [Value ("martId"),
                                          Lambda (b,
                                                  PropertyGet (Some (b), martId,
                                                               []))]))]),
               Application (Lambda (arg00,
                                    Lambda (arg10,
                                            Call (None,
                                                  ConcreteCodec`4.apply.Static,
                                                  [arg00, arg10]))),
                            Call (None, jopt,
                                  [Value ("test_oneof"),
                                   Lambda (a,
                                           PropertyGet (Some (a), test_oneof, []))]))]))

If we can quote the named versions I don't see why the operator version will not work either? Is this an artificial constraint or an edge case that has not yet been plumbed in?

Expected behavior

The expressions that can be quoted with a named function should be able to be quoted with an operator version.

Actual behavior

Only the named function version can be quoted

Known workarounds

Don't use operators, although the code in this instance is not as well defined as using the operators, the operator style combinators in fleece is easy to understand and has no parenthesis.

Related information

Provide any related information

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions