我可以在F#成员函数上指定函数类型吗?

时间:2015-10-02 02:35:49

标签: f# unit-type

我目前正在使用F#中的Eto.Forms。我遇到的一个小麻烦是,当您在外部文件(XAML或JSON)中定义GUI对象(表单,面板,按钮等)并声明事件处理程序时,这些事件处理程序必须具有特定类型:

member public this.OnFirstButtonClicked (sender:Object, e:EventArgs) ->
    MessageBox.Show(this, "First button was clicked")
    |> ignore
member public this.OnSecondButtonClicked (sender:Object, e:EventArgs) ->
    MessageBox.Show(this, "Second button was clicked")
    |> ignore

类型签名的重复让我烦恼。 (在这两个函数中实际上有很多重复,比如调用带有几乎不同参数的MessageBox,但这只是一个测试项目。在一个真实的项目中,我会做一些不同的事情。这两个按钮。)我不想每次都重复这些功能的类型签名。阅读this page at F Sharp For Fun and Profit后,我想我可以这样做:

type EventHandler = (Object * EventArgs) -> unit

member public this.OnFirstButtonClicked : EventHandler ->
    MessageBox.Show(this, "First button was clicked")
    |> ignore
member public this.OnSecondButtonClicked : EventHandler ->
    MessageBox.Show(this, "Second button was clicked")
    |> ignore

然而,当我尝试这个时,我发现在成员函数上,语法实际上意味着"这个函数返回一个EventHandler函数"。我想说"这个成员函数 是一个EventHandler函数",我不知道该怎么做。

更新:自从撰写上述问题以来,我了解到我实际上并不需要指定事件处理函数的类型签名'参数。以下内容适用:

member public this.OnFirstButtonClicked (sender, e) ->
    MessageBox.Show(this, "First button was clicked")
    |> ignore
member public this.OnSecondButtonClicked (sender, e) ->
    MessageBox.Show(this, "Second button was clicked")
    |> ignore

然而,我真正的问题不是如何使这些事件处理程序工作?"我真正的问题是,"我已经学会了如何指定不是类的成员的函数的类型,但是我该怎么做呢? 是一个类的成员吗?"

2 个答案:

答案 0 :(得分:1)

我将使用一些更简单的类型,但这里的想法是一样的。

考虑一个简单的类型:

type t() = member x.Test()  = ();;

此处Test明显具有unit -> unit

类型

现在,我们尝试重写此内容以避免()

type t() = member x.Test : unit -> unit  = ();;

但这会失败,因为右侧的值不正确。

这是一个解决方案:

type t() = member x.Test : unit -> unit  = fun () -> () ;;

您可能尝试接近所需的一种解决方案是使用_作为忽略的参数:

type t() = member x.Test _ : unit -> unit  =  () ;;

但这不起作用,因为我们现在是一个接受单个参数并返回一个函数的函数。

此时,我们真正想要的是Signature file,它将允许指定成员的类型签名。或者你可以尝试一个界面。

最后一种方法是在函数内部移动参数 - 然后它将成为

type t() = member x.Test : some signature = fun .....

答案 1 :(得分:1)

独立函数定义和方法定义之间的唯一区别是member关键字和自标识符。除此之外,语法是相同的。

再次检查F# for fun and profit

上的示例
type AdditionFunction = int->int->int
let f:AdditionFunction = fun a b -> a + b

它实际上是一个值绑定,而不是一个函数绑定。该函数使用lambda表达式fun a b -> a + b定义并绑定到标识符f。

要使用此类定义,您必须将事件处理程序定义为

type EventHandler = (Object * EventArgs) -> unit

member public this.OnFirstButtonClicked : EventHandler =
    fun (_, _) ->
        MessageBox.Show(this, "First button was clicked")
        |> ignore

同样,对于独立功能,它的工作方式完全相同。