开发者

F# - Pipeline with tupled parameters

开发者 https://www.devze.com 2023-02-28 12:34 出处:网络
Is it possible to somehow use a pipeline to pass开发者_如何学编程 in the last argument of a method with tupled parameters?

Is it possible to somehow use a pipeline to pass开发者_如何学编程 in the last argument of a method with tupled parameters?

An example:

// Member to call

static member Property (expr:Expr<'a -> string>, cfg:EntityInfo<'a>) = cfg.Property expr

// My curry function

let curry f x y = f (x,y)

// My EntityInfo<FileUpload>

let entityInfo = EF.Entity<FileUpload> modelBuilder

I want to be able to call it like:

entityInfo |> curry EF.Property <@ fun z -> z.Path @>

instead of

EF.Property(<@ fun z -> z.Path @>, entityInfo)


I believe that this is a simplified version of your problem (although you're excluding too much code to be sure):

type T() = class end

type S =
    static member Method(_:int, T) = 'c'
    static member Method(_:string, T) = false

let curry f x y = f(x,y)

// won't work
T() |> curry S.Method 1

As Brian mentions, overloading doesn't play nicely with type inference. In particular, since F#'s type inference works left-to-right, the compiler does not use the fact that 1 is an int when trying to do the member lookup for S.Method, which means that it can't identify the correct overload. As I see it, you have a few options:

  1. Use distinct method names. Is there a reason that you have to use Property to refer to multiple different operations? Would it be much worse to use StringProperty, IntProperty, etc. for each overload? In general, overloading makes life harder for the compiler (and often for human maintainers, too). As an aside, I don't like the idea of naming a method Property, anyway...
  2. Use explicit type parameters on curry, and specify them. E.g.

    let curry<'a,'b,'c> f (x:'a) (y:'b) : 'c = f(x,y)
    entityInfo |> curry<Expr<_ -> string>,_,_> EF.Property <@ fun z -> z.Path @>
    
  3. Explicitly indicate the type of EF.Property:

    entityInfo |> curry (EF.Property: Expr<_ -> string> * _ -> _) <@ fun z -> z.Path @>
    

Of course, these last two options aren't very concise, so they may defeat the purpose of using the pipelined style.


It is because it is counting entity info as an member of EF.Propery method instead of curry method, you should use

entityInfo |> curry (EF.Property) (<@ fun z -> z.Path @>)
0

精彩评论

暂无评论...
验证码 换一张
取 消