foo 20 |> bar "B" |> -6ren">
gpt4 book ai didi

f# - 如何为交错函数调用创建类型安全的 DSL

转载 作者:行者123 更新时间:2023-12-03 22:43:06 25 4
gpt4 key购买 nike

我想创建一个 DSL,其中可以连续调用 2 个( foobar )函数,以便

initialize()
|> foo 10
|> bar "A"
|> foo 20
|> bar "B"
|> transform

通过定义,这非常完美
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)

但是现在我也想允许多个 bar调用可以连续执行,但是 foo s 仍然只需要调用一次
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

在 C# 中,我可以重载 bar要么接受 BarResult 要么 FooResult 但这不适用于 F#。至少不容易。
我还尝试创建一些歧视性工会,但我真的无法理解它。

最佳答案

这是一个有趣的问题!

您现有的代码工作得很好,但我会做一个更改 - 您实际上不需要传递实际的 FooResultBarResult值(value)观。你可以定义一个类型MarkedType<'TPhantom, 'TValue>表示值 'TValue带有其他类型指定的特殊“标记”:

type MarkedValue<'TPhantom, 'TValue> = Value of 'TValue

然后,您可以使用接口(interface)作为幻像类型的类型参数。我发现考虑“结果”有点困难,所以我将使用输入来代替:
type IFooInput = interface end
type IBarInput = interface end

现在的诀窍是,您还可以定义一个同时为 IFooInput 的接口(interface)。和 IBarInput :
type IFooOrBarInput =
inherit IFooInput
inherit IBarInput

因此,您现在需要做的就是向 foo 添加适当的注释。和 bar :
let foo param (Value v : MarkedValue<#IFooInput, _>) : MarkedValue<IBarInput, _> = 
Value 0

let bar param (Value v : MarkedValue<#IBarInput, _>) : MarkedValue<IFooOrBarInput, _> =
Value 0

在这里,输入上的注释说它应该接受任何从 IFooInput 继承或继承的东西。或 IBarInput .但是 bar 的结果函数标有 IFooOrBarInput , 这样就可以将它传递给 foobar :
(Value 0 : MarkedValue<IFooInput, _>)
|> foo 10
|> bar "A"
|> bar "A"
|> foo 20
|> bar "B"

关于f# - 如何为交错函数调用创建类型安全的 DSL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27783736/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com