I'm trying this:
type TS1<'state, 'action> = {
actions : 'state -> #seq<'action>
move : 'state -> 'action -> 'state
state0 : 'state
}
But the type checker won't let me:
.../stdin(2,29):error FS0715: Anonymous type variables are not permitted in this declaration
However, if I unfold the definition of the flexible type, I'm good:
type TS2<'state, 'action, 'actions when 'actions :> seq<'action>> = {
actions : 'state -> 'actions
move : 'state -> 'action -> 'state
state0 : 'state
}
I'm unhappy with having to add the 'actions
type variable—it makes the connection to deterministic transition systems as mathematical objects less obvious.
I don't see what could go wrong by allowing flexible types in record definitions. Is it somehow dangerous? Is there some other way I could get the clarity of definition I would like?
Update. I was hoping to be able to write functions on TS types that exploits known implementations; i.e., I want to be able to define a function
let has_action a ts s = Set.contains a <| ts.actions s
This obviously won't type if the type of the actions member is actions : 'state -> seq<'action>
. I can do it with the second definition, in which case has_action
has type
has_action : a:'a -> ts:TS2<'s,'a,Set<'a>> -> s:'s -> bool when 'a : comparison
The type of this example suggests that the flexible type in TS1 perhaps wouldn't help. There is no way I can avoid the messy third type parameter in TS2? It seems to me the exact implementation of the collection of actions for a state is an implementation detail that should not be exposed in the type.
#
from before theseq
. – Chalybeate#
- why do you think you need it? – Cutback_
instead if you like) - in case you want to know (but it will not help here): the only place where you can useforall
quantification is on (interface)members (I wrote about a similar issue here: gettingsharper.de/2014/09/29/…) – Cutbackhas_parents
it seems there's no way around having a third type parameter. – Allocution