我正在使用F#,我很难构建我的商业模型。假设我有一个float列表和两种可以应用于它的转换类型。举例:
类型转换=|期间SMA:期间|周期的P2MA:周期
然后我定义了一个函数let compute Transformation list
来计算列表上的任何类型的变换。
通过上述转换类型,我可以创建SMA(3(或P2SMA(5(作为示例。
我希望能够以我可以写SMA(3,P2SMA(5,SMA(10((的方式嵌套转换。但我也希望仍然能够写SMA(2(。我尝试过使用选项,但我认为写SMA(3,None(或SMA(3、Some(P2SMA(5(((太冗长了。
有办法做到这一点吗?也许我的方法是错误的,因为我是F#的新手,我可能会用错误的方式来解决问题?
非常感谢的帮助
在这里试试我的答案。
不可能完全按照你想要的方式超载歧视工会的案件。但如果你接受一个稍微不同的语法,你可以这样做:
type Period = int
type SmaTransform =
| Sma of Period
| Sma' of Period * Transform
and P2smaTransform =
| P2sma of Period
| P2sma' of Period * Transform
and Transform =
| OfSma of SmaTransform
| OfP2Sma of P2smaTransform
let SMA(period) =
Sma(period) |> OfSma
let SMA'(period, transform) =
Sma'(period, transform) |> OfSma
let P2SMA(period) =
P2sma(period) |> OfP2Sma
let P2SMA'(period, transform) =
P2sma'(period, transform) |> OfP2Sma
let transforms =
[|
SMA(3)
P2SMA(5)
SMA'(3, P2SMA'(5, SMA(10)))
|]
for transform in transforms do
printfn "%A" transform
与所需语法的唯一区别是表示嵌套转换的撇号。
我尝试过使用选项,但我认为编写SMA(3,None(或SMA(3、Some(P2SMA(5(((太冗长了。
您可以使用带有可选参数的静态成员:
type Transformation =
| [<EditorBrowsable(EditorBrowsableState.Never)>]
SMAInternal of period:int * inner: Transformation option
...
static member SMA(period:int, ?t:Transformation) =
SMAInternal(period, t)
然后可以编写:Transformation.SMA(3)
或Transformation.SMA(3, Transformation.P2SMA(5))
。这需要更多的字符,但结构较少。你可能会也可能不会认为它更简洁。
我是F#的新手,我可能会用错误的方式解决这个问题?
如果要在代码文件中定义数百个这样的东西,那么使用上述方法并缩短名称Transformation
可能是个好主意。否则,只需使用Somes和Nones。冗长是一个微不足道的考虑因素,如果你开始担心它,可怕的事情就会开始发生。
我不太明白你试图建模什么,但这里有一些类似的东西。
我的转换要么是一个数字的倍数,要么加上
type Trans =
| Mult of period: int
| Add of period: int
我现在可以写一个解释函数,给定一个数字和一个变换,我可以解释它
let interpret x trans =
match trans with
| Mult p -> p * x
| Add p -> p + x
所以我们现在可以做简单的事情设x=解释1(Mult 2(
但你想把转换串起来?所以让我们允许。。
let interprets xs x =
List.fold (fun state trans ->
interpret state trans) x xs
我们可以去。。。
let foo = [ Mult 3; Add 2 ]
let bar = interprets foo 1
好吧,如果你真的想统一处理这些转换列表的组合,这可能很好(有点像函数组合(。
然后我会很想去(注意,我正试图遵循你的编码风格((这里有很多东西需要学习,所以也许可以坚持上面的方法,直到你对F#的理解更好为止(。
type Trans =
| Mult of period: int
| Add of period: int
| Compose of chain: List<Trans>
let rec interpret x trans =
let interprets xs x =
List.fold (fun state trans ->
interpret state trans) x xs
match trans with
| Mult p -> p * x
| Add p -> p + x
| Compose ps ->
interprets ps x
let two = interpret 1 (Mult 2)
let three = interpret 1 (Compose [ Mult 2; Add 1 ])
现在我认为你有一个数据模型;作品";,而且非常简单。
然后,我不会试图更改数据模型以方便您的代码,我会创建实用程序函数来实现这一点(智能构造函数(。
例如
let multThen x trans = Compose [ Mult x; trans ]
let addThen x trans = Compose [ Add x; trans ]
不过,建议是让数据模型以最简单的方式对数据进行建模,然后使用函数使代码变得优雅,并在模型中映射和映射,通常这两件事看起来完全不同。
注意:我还没有测试一些代码