【问题标题】:F#: currying differences between functions and static membersF#:函数和静态成员之间的柯里化差异
【发布时间】:2015-06-12 05:53:24
【问题描述】:

请有人向我解释一下:

type IItem = interface end
type Item = {i:int} interface IItem

type Fail = static member foo (s:string) = fun (x:IItem) -> ""
let foo = fun (s:string) -> fun (x:IItem) -> ""

let works = {i=1} |> foo ""
let fails = {i=1} |> Fail.foo ""

为什么使用静态成员函数的柯里化不起作用? 如果这很重要,我正在使用带有 .net 4.5.2 的 Visual Studio 2012。

【问题讨论】:

  • 说实话 - 更好的问题是:为什么 works 有效 - 因为两者都想要 IItem 而你给他们 Item (F# 通常不做隐式转换) -我想这就是你的答案 - 第一个执行隐式转换,而第二个不执行
  • 顺便说一句:你得到faillet fails = ({i=1} :> IItem) |> Fail.foo ""工作
  • PS:type Fail = static member foo (s:string) (x:IItem) = "" 也是如此 - 我认为这是静态成员和 lambda 的边缘情况(你可以在签名中看到它:string -> (IItem -> string) vs string -> IItem -> string 这使得从理论的角度来看没有意义 - 我相信 Tomas 或其他具有深厚规范知识的人会过来告诉我们确切原因;)
  • 我认为这可能是因为static member 并不总是FSharpFunc ...但在这里我开始猜测 - 这是一个有趣的问题,我希望我现在有更多时间做一些研究
  • @FyodorSoikin foo 在这里工作 - 这是不寻常的书面 foo 静态成员,它的工作方式不同(尽管乍一看它看起来非常相似) - 我不会称之为 错误,但 IMO 离它不远(string -> IItem -> stringstring -> (IItem -> string) 之间应该没有语义差异 - 实际上你通常会告诉人们这些是相同的)跨度>

标签: f# currying


【解决方案1】:

这并不是静态成员和函数之间的真正区别——它有点微妙。这是另一个重现:

type T =
    static member A () (o:obj) = ()
    static member B () = fun (o:obj) -> ()

T.A () 1 // ok
T.B () 1 // huh?

请注意T.AT.B 的签名是不同的(这实际上在规范的第11.2.1.1 节中有介绍):

type T =
  class
    static member A : unit -> o:obj -> unit
    static member B : unit -> (obj -> unit)
  end

这是一个通常不重要的区别,但基本上它意味着在 .NET 表示级别 A 被编译为具有两个参数的方法(即使它在 F# 中看起来是 curried),而 B 被编译为具有单个参数的方法,该方法返回 F# 函数。这种差异最终导致了您所看到的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-14
    • 2011-02-11
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-01
    • 1970-01-01
    相关资源
    最近更新 更多