我想创建一个DSL,其中可以连续调用2(foo
和bar
)函数,以便
initialize()
|> foo 10
|> bar "A"
|> foo 20
|> bar "B"
|> transform
Run Code Online (Sandbox Code Playgroud)
这通过定义非常完美
type FooResult = FooResult
type BarResult = BarResult
let foo param (result_type:BarResult, result) = (FooResult, transform param result)
let bar param (result_type:FooResult, result) = (BarResult, transform param result)
Run Code Online (Sandbox Code Playgroud)
现在我想要允许多个bar
调用可以连续执行,但是foo
仍然只需要调用一次
initialize()
|> foo 10
|> bar "A"
//OK
|> bar "B"
|> transform
initialize()
|> foo 10
|> bar "A"
|> foo 20
//should yield an compile error
|> foo 30
|> bar "B"
|> transform
Run Code Online (Sandbox Code Playgroud)
在C#中,我可以重载bar
接受BarResult或FooResult,但这对F#不起作用.至少不容易.我也试图建立一些判别联盟,但我真的无法理解它.
Tom*_*cek 14
这是一个有趣的问题!
你现有的代码工作得很好,但我会做一个改变 - 你实际上并不需要传递实际值FooResult
和BarResult
值.您可以使用另一种类型指定的特殊"标记" 来定义MarkedType<'TPhantom, 'TValue>
表示值的'TValue
类型:
type MarkedValue<'TPhantom, 'TValue> = Value of 'TValue
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用接口作为幻像类型的类型参数.我发现考虑"结果"有点困难,所以我将改用输入:
type IFooInput = interface end
type IBarInput = interface end
Run Code Online (Sandbox Code Playgroud)
诀窍是现在,你也可以定义一个接口,既IFooInput
和IBarInput
:
type IFooOrBarInput =
inherit IFooInput
inherit IBarInput
Run Code Online (Sandbox Code Playgroud)
所以,你现在需要做的催产素是适当的添加注解foo
和bar
:
let foo param (Value v : MarkedValue<#IFooInput, _>) : MarkedValue<IBarInput, _> =
Value 0
let bar param (Value v : MarkedValue<#IBarInput, _>) : MarkedValue<IFooOrBarInput, _> =
Value 0
Run Code Online (Sandbox Code Playgroud)
这里,输入上的注释说它应该接受任何或继承自IFooInput
或IBarInput
.但是bar
函数的结果标有IFooOrBarInput
,这使得可以将它传递给两者foo
和bar
:
(Value 0 : MarkedValue<IFooInput, _>)
|> foo 10
|> bar "A"
|> bar "A"
|> foo 20
|> bar "B"
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
589 次 |
最近记录: |