15.6.2_定义基元

15.6.2 定义基元

 

    首先要定义将要处理的值类型,然后,实现几个可以在以后组合的基元。基元数据类型叫 Contract,表示可能出现在特定日期和时间的交易。

 

声明 CONTRACT 类型

 

    你可以看到在清单 15.23 中,Contract 类型与动画示例中的行为类型很相似,它是一个差别联合,只有一个识别器,名为 ContractFunc。这是我们一直在使用一种技巧,当定义行为时,它给了我们一种方法,可以创建简单、命名和封装的函数值。

 

Listing 15.23 Type representing financial contracts (F# Interactive)

 

> type Contract =
     | ContractFunc of (DateTime -&gt; seq<string * int>);;
(...)
&gt; let eval_r(ContractFunc f) dt = f(dt) |&gt; List.ofSeq;;
val eval : Contract -&gt; DateTime -&gt; (string * int) list

 

    此函数表示实际合同带有一个参数,并返回一个元组序列。当我们用特定的日期调用它时,将生成所有发生在该日期的交易。每笔交易表示为一个元组,包含股票的名称和想要购买或出售的股票数量。我们将用正数表示购买股票数量,负数表示出售数量。

    清单15.23 的第二部分实现 eval 函数,计算在给定时间的合同,并返回的列表。我们使用一个序列来表示中的合同,因为,这会使代码更通用。我们看到动态生成序列并组合它们,是多么容易。Eval 函数返回一个列表,因为,从调用者的角度来看,更容易地处理。

 

实现组合

 

    有了表示我们的语言值的数据类型以后,就需要实现几个基本函数,来创建和组合这些值。对于行为,我们创建了基元值,比如,wiggle,和提升运算符来组合它们。在我们的合同语言中,从函数 trade 开始,创建一个表示可以发生在任何时间的购买合同。要组合合同,需要提供函数 combine,它把两份不同的合同加到这个交易中。

    清单 15.24 显示了这两个函数的实现,以及对于限定日期可能发生的合同的函数,和创建由合同所代表的我们准备出售股票交易的函数。

 

Listing 15.24 Combinators for creating and composing contracts (F# Interactive)

 

&gt; let trade what amount = ContractFunc(fun _ �C&gt;
     seq { yield what, amount })
   let combine (ContractFunc a) (ContractFunc b) =
     ContractFunc(fun now �C&gt;
       Seq.concat [ a(now); b(now) ])
;;
val trade : int -&gt; string -&gt; Contract
val combine : Contract -&gt; Contract �C&gt; Contract

&gt; let after dt (ContractFunc f) = ContractFunc(fun now �C&gt;
     seq { if now &gt;= dt then yield! f(now) })
   let until dt (ContractFunc f) = ContractFunc(fun now �C&gt;
     seq { if now <= dt then yield! f(now) })
   let sell (ContractFunc f) = ContractFunc(fun now �C>
     seq { for itm, am in f(now) -&gt; itm, -am })
;;
val after : DateTime -&gt; Contract -&gt; Contract
val until : DateTime -&gt; Contract -&gt; Contract
val sell : Contract �C&gt; Contract

 

    可以在任何时间发生的单笔交易被表示为一个函数,将忽略其参数(我们计算合同的日期),并返回只有一个元素的序列。组合也简单,因为我们连接发生在给定日期的两个基础合同下所有的交易。

    接下来两个基元,在限定日期哪些合同是活动的。其实现是通过创建一个函数,测试给定的日期是否匹配基元的条件。当测试成功时,返回所有基础交易,使用 yield! 基元;否则,返回一个空序列。最后的基元可以用于修改合约是出售还是购买。 我们遍历一个合同的所有基础交易,把正的数量改为负,或相反。

    虽然我们只是大概地勾画出这个库,但已经实现的几个基元就能够描述许多有趣的情景了。

你可能感兴趣的:(动画,技巧,休闲,联合,识别器)