我可以在F#中表达具有类型约束的泛型类型的递归关系吗?

时间:2017-07-20 19:50:14

标签: 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#在类型级别进行编码?

2 个答案:

答案 0 :(得分:5)

除非你的描述遗漏了一些令它变得不可行的细节,否则有一个相当简单的编码,甚至不要求该类型是通用的:

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的倒置机制,用于流量控制。

答案 1 :(得分:3)

这是不可能的。如果要实现它,那将意味着工作流本身将包含无限的泛型序列,这在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

很容易看出,为了创建一个Workflow类,我们需要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

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

请注意,此类型的类型列表确实有一个名称,并且它以某种语言实现,称为可变参数类型。