Can I express recursive generic type relationships with type constraints in F #?

Given the following type

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

      

I would like to express the fact that 'next

, 'prev

and 'cancel

must also be of type WorkflowStep

or type unit

, is it possible to code at the type level using F #?

+3


source to share


2 answers


If your description is missing some details that would make it impracticable, there is a fairly simple encoding that doesn't even require the type to be generic:

type Transition =
    | Step of WorkflowStep
    | Done

 and WorkflowStep =
     abstract member Next : unit -> Transition
     abstract member Prev : unit -> Transition
     abstract member Cancel : unit -> Transition

      



where Transition

captures your requirement for WorkflowStep

either doing another step or the value of one. This gives you a kind of flipped CPS-like flow control mechanism.

+5


source


It's impossible. If this were implemented, it would mean that the workflow itself would contain an endless sequence of generics, which is unfortunately not supported in f #.

Below is a more detailed explanation of why using a simplified version of your workflow type is given above.

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

      

However, when we specify a type parameter for the returned workflow, it now requires 2 parameters to apply.

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

      



It's easy to see that to create a Workflow class, we need an infinite number of common arguments that f # doesn't support.

One alternative is to specify that your workflow type can only run on one workflow, if your resulting code looks something like this.

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

      

The parameter type you see above allows you to return either a value (Some) or one (None)

Note that this type of type list has a name and is implemented in some language called a variation type.

+3


source







All Articles