是否可以在 F# 中使用类型约束来表示泛型类型的递归关系?



给定以下类型

type WorkflowStep<'next, 'prev, 'cancel> =
abstract member Next : unit -> 'next
abstract member Prev : unit -> 'prev
abstract member Cancel : unit -> 'cancel

我想表达这样一个事实,即'next'prev'cancel也应该是WorkflowStep类型或类型unit是否可以使用 F# 在类型级别进行编码?

除非你的描述缺少一些细节,使其不可行,否则有一个相当简单的编码,甚至不需要类型是泛型的:

type Transition =
| Step of WorkflowStep
| Done
and WorkflowStep =
abstract member Next : unit -> Transition
abstract member Prev : unit -> Transition
abstract member Cancel : unit -> Transition

其中Transition捕获您对WorkflowStep生成另一个步骤或单位值的要求。这为您提供了一种倒置的、类似 CPS 的流量控制机制。

这是不可能的。如果要实现这一点,则意味着工作流本身将包含无限的泛型序列,遗憾的是f#不支持该序列。

下面更详细地解释了为什么使用上面提供的工作流类型的简化版本。

//error workflow must be provided a type
type Workflow<'t when 't :> Workflow<_>> = 
abstract member Next : unit -> 't

但是,当我们指定类型参数时 对于返回的工作流,现在需要应用 2 个参数。

//workflow now requires 2 parameters
type Workflow<'nextvalue, 't when t:>Workflow<'nextvalue>>
abstract member Next : unit->'t

很容易看出,为了创建一个工作流类,我们需要无限数量的泛型参数,而 f# 不支持这些参数。

一种替代方法是指定工作流类型只能处理一个工作流,如果生成代码如下所示。

type Workflow<'value> = 
abstract member Next : unit -> Workflow<'value> option
abstract member Prev : unit -> Workflow<'value> option
abstract member Cancel : unit -> Workflow<'value> option

您在上面看到的选项类型是,您可以返回值(一些(或单位(无(

请注意,这种类型的类型列表确实有一个名称,它在某些语言中实现,称为可变参数类型。

最新更新