F#带有可选递归组件的判别并集



我正在使用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 ]

不过,建议是让数据模型以最简单的方式对数据进行建模,然后使用函数使代码变得优雅,并在模型中映射和映射,通常这两件事看起来完全不同。

注意:我还没有测试一些代码

最新更新