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 #?
source to share
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.
source to share
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.
source to share