有人能指出我在F#中进行多范式(对象功能)编程的例子吗?

时间:2010-11-06 18:18:29

标签: oop f# functional-programming

有人能指出我在F#中进行多范式(对象功能)编程的例子吗?

我特意寻找结合OO和amp;函数式编程。有很多关于F#如何是混合语言的讨论,但是我找不到演示多范式编程示例的例子。

由于

5 个答案:

答案 0 :(得分:9)

我用F#做了一个小的(600行)Tetris克隆,使用XNA进行面向对象。代码是旧的(使用#light),并不是你将看到的最漂亮的代码,但它绝对是OOP和功能的混合。它由十个班组成。我不认为我传递任何一流的函数,但它是programming the small中F#功能的一个很好的例子。

  • MyGame - 继承XNA主游戏类,是程序入口点。
  • Board - 跟踪不再移动的碎片并完成水平线。
  • UI - 用户界面只有bool stateMenu处理的两种状态(播放和主菜单)
  • Tetris - 处理游戏状态。游戏结束和片断碰撞。
  • Piece - 定义不同的俄罗斯方块形状及其移动和绘图。
  • Player - 处理用户输入。
  • Shape - 映射到primative的基本图形对象。
  • Primative - 包装顶点基元类型。

我做了一个粗略的课程图来帮助。如果您有任何疑问,请随时在评论部分询问。

alt text

答案 1 :(得分:6)

将功能和面向对象的范例结合起来有两种方法。在某种程度上,它们是独立的,您可以编写使用类型(写为F#对象)构造的不可变(功能)代码。像这样编写的Client类型的F#示例是:

// Functional 'Client' class
type Client(name, income) =
  // Memebers are immutable
  member x.Name = name
  member x.Income = income

  // Returns a new instance 
  member x.WithIncome(ninc) =
    new Client(name, ninc)
  member x.Report() =
    printfn "%s %d" name income

请注意,WithIncome方法(“更改”客户的收入)实际上并没有做任何修改 - 它遵循功能样式并创建一个新的,更新的客户端并将其作为结果返回

另一方面,在F#中,您还可以编写具有可变公共属性的面向对象代码,但在封面下使用一些不可变数据结构。当你有一些很好的功能代码并希望以传统的(命令式/面向对象的)方式将它暴露给C#程序员时,这可能很有用:

type ClientList() =
  // The list itself is immutable, but the private
  // field of the ClientList type can change
  let mutable clients = []
  // Imperative object-oriented method
  member x.Add(name, income) =
    clients <- (new Client(name, income))::clients
  // Purely functional - filtering of clients
  member x.Filter f = 
    clients |> List.filter f

(这个例子来自我书中Chapter 9的源代码。还有一些不可变的面向对象代码的例子,例如第14章中的并行模拟。)

答案 2 :(得分:4)

我已经混合OO(特别是突变)和函数式编程的最强大的经验是通过在内部使用可变数据结构同时享受外部用户的不可变性的所有好处来实现性能提升。一个很好的例子是我写的一个算法的实现,它产生了你可以找到here的词典排列。我使用的算法在其核心(数组的重复变异步骤)中势在必行,如果使用功能数据结构实现,则会受到影响。通过获取输入数组,最初制作它的只读副本以使输入不被破坏,然后在执行算法的变异步骤之后在序列表达式中产生它的只读副本,我们达到了良好的平衡OO和功能技术之间。链接的答案引用了原始的C ++实现以及其他纯功能实现答案的基准。我的混合OO /功能实现的性能介于OO C ++解决方案和纯功能F#解决方案的卓越性能之间。

在整个F#库中使用这种在内部使用OO /可变状态同时保持调用者外部纯度的策略,特别是在Seq模块中直接使用IEnumerator。

另一个例子可以通过比较使用可变字典实现与不可变Map实现的memoization来找到,Don Syme探讨了here。不可变的Dictionary实现比Map实现更快但使用纯度更低。

总之,我认为在F#中使用可变OO对于寻求性能提升的图书馆设计者来说是最强大的,同时保持图书馆消费者的所有功能。

答案 3 :(得分:3)

我不知道任何F#,但我可以向您展示您在Scala中寻找的确切语言机制的示例。如果这没有用,请忽略它。

class Summation {

    def sum(aLow : Int, aHigh : Int) = {
        (aLow to aHigh).foldLeft(0) { (result, number) => result + number }
    }

}

object Sample {

    def main(args : Array[String]) {
        println(new Summation sum(1, 10))
    }

}

我试着让它变得非常简单。请注意,我们声明了一个类来对一个范围求和,但该实现与一个函数样式一起使用。通过这种方式,我们可以抽象出用于实现一段代码的范例。

答案 4 :(得分:2)

我不了解F#,但大多数用Scala编写的软件本质上都是对象功能。

Scala编译器可能是对象功能软件的最大和最先进的示例。其他值得注意的示例包括AkkaLiftSBTKestrel等。(谷歌搜索将为您找到更多对象功能的Scala示例。)