15.6.3 使用建模语言

来源:互联网 发布:qt 信号 传递数组 编辑:程序博客网 时间:2024/06/11 22:24
 

15.6.3 使用建模语言

 

    也许有关可组合库最有价值的事情,就是可以使用由库设计人员提供基本的基元,通过组合,来创建更复杂的函数。这样,就让库更灵活,因为库的用户(这里的金融专家)可以创建他们需要的基元。作为核心库的设计人员,我们只需要提供足够丰富的基元,允许用户建立更多的。

    清单 15.25 演示这样定义的两个函数,根据刚刚创建的基元。第一个定义的函数,生成一个交易窗口:在一个时间间隔内,哪个交易可能发生。第二个函数提供了特定种类的交易窗口:交易只发生在一个日期。

 

Listing 15.25 Implementing derived financial contract functions (F# Interactive)

 

> let between dateFrom dateTo contract =
     after dateFrom (until dateTo contract);;
val between : DateTime -> DateTime -> Contract –> Contract

> let tradeAt date what amount =
     between date date (trade what amount);;
val tradeAt : DateTime -> int -> string –> Contract

 

    第一个函数由为限制合同日期而定义的两个基元组成,它的参数是开始和结束的日期,以及限制的合同,返回在指定的时间间隔之前或之后都不会发生的合同。原始合同可以包括已经受到以某种其他方式限制的交易。第二个函数创建基元交易,正好发生在指定的日期。它使用 trade 函数来构建一个基本的交易,然后,使用 between 函数限制其效力。注意,after 和 until 函数使用允许等号的运算符(>= 和 <=),所以,between 函数使用相同值的两次,不会创建一个不可能的交易。

    有了这些用于创建和组合合同函数的准备,就可以尝试写一些合同,计算哪一交易可以作为合同的一部分发生在两个不同的日期。清单 15.26 显示了一个合同,我们打算在一个特定的日期出售 500 股谷歌,可以在特定的 10 天内的任何时间买 1000 股微软。

 

Listing 15.26 Creating and evaluating sample contract (F# Interactive)

 

> let dfrom, dto = DateTime(2009, 4, 10), DateTime(2009, 4, 19)
   let itstocks =
     combine (sell (tradeAt (DateTime(2009, 4, 15)) "GOOG" 500))
                 (between dfrom dto (trade "MSFT" 1000));;
val itstocks : Contract = ContractFunc <fun:trade@6>

> eval itstocks (DateTime(2009, 4, 14));;
val it : (string * int) list = [("MSFT", 1000)]

> eval itstocks (DateTime(2009, 4, 15));;
val it : (string * int) list = [("GOOG", -500); ("MSFT", 1000)]

 

    清单 15.26 首先创建一些值,表示我们打算购买微软股价两个日期区间。然后我们定义一个值 itstocks,表示合同。我们使用 combine 基元,合并两个可能的交易。第一个是出售谷歌股票。构建出售的一种方法,是创建一个表示购买股票的合同(使用在清单 15.25 中实现的 tradeAt 函数),然后使用 sell 基元,把购买变成出售。通过这种方式,我们可以创建可重用的交易,并使用它们来写出售和购买。另外,我们可以使用 tradeAt (DateTime(2009, 4, 15)) "GOOG" -500)。第二个交易是在 10 天内购买微软股票。

    我们定义了合同以后,就可以计算了。合同表示交易的规范,可在一些指定的日期发生,所以,可以通过提供该日期计算。你可以看到在输出中,第一个日期的结果是购买微软股票;第二个日期,我们会得到两个交易。

 

把合同表示为抽象值

 

    在此示例中,我们表合同的方式非常类似于表示行为的语言。基本上是用函数来计算交易,然后写连接符(combinators)组合这些函数。这是我们在这一章的开头提到的两种基本方法中的一种。

    另一个选项是设计差别联合,把合同表示为数据,而不是计算。我们可以使用不同的选项,包括不同的基元。它可能看起来像这样:

 

type Contract =
  | Exchange of string * int
  | After of DateTime * Contract
  | Until of DateTime * Contract
  | Combine of Contract * Contract

 

    这个类型是递归的,所以我们可以组合基本值 Exchange,表示一个交易,使用 Combine 与其他交易组合,使用 After 和 Until限制其有效性,等等。

    这两种技术的一个区别是:当我们使用抽象值表示时,可以写出这种语言所有类型的处理函数,知道特定的限制。我们可以添加一个函数,取一个 Contract 值,计算其整体的值。另一方面,当使用在后台的函数类型时,值一经创建,不能观察许多属性,只能执行它。事实上,使用抽象值表示合同,可能会更实际,但是,我们是想要演示,早先看到的用于动画而创建的语言的技术,如何用于非常不同的域中。

 

    很明显,我们在这里描述的特定域的语言,是有限的和简单化的,但它表现出的方法,是适用于各种问题域。希望你已经打算在自己的开发中可以适用哪些情况。

原创粉丝点击