F# - 具有tupled参数的管道

时间:2011-04-21 18:34:33

标签: f#

是否有可能以某种方式使用管道传递带有tupled参数的方法的最后一个参数?

一个例子:

// 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

我希望能够称之为:

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

而不是

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

2 个答案:

答案 0 :(得分:2)

我认为这是您问题的简化版本(尽管您要排除太多代码以确定):

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

正如布莱恩所提到的,重载不能很好地与类型推断发挥作用。特别是,由于F#的类型推断从左到右工作,编译器在尝试对1进行成员查找时不使用intS.Method的事实,这意味着它无法识别正确的过载。在我看来,你有几个选择:

  1. 使用不同的方法名称。您是否有必要使用Property来引用多个不同的操作?每次重载使用StringPropertyIntProperty等会更糟吗?通常,重载会使编译器的生活变得更加困难(对于人类维护者来说也是如此)。顺便说一句,我不喜欢命名方法Property的想法,无论如何......
  2. curry上使用显式类型参数,并指定它们。 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. 明确指出EF.Property的类型:

    entityInfo |> curry (EF.Property: Expr<_ -> string> * _ -> _) <@ fun z -> z.Path @>
    
  4. 当然,最后两个选项并不是非常简洁,因此它们可能会破坏使用流水线样式的目的。

答案 1 :(得分:0)

这是因为它将实体信息计为EF.Property方法的成员而不是咖喱方法,你应该使用

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