2015-03-26 3 views
5

sto cercando questo:Perché i tipi flessibili non sono consentiti nelle definizioni dei tipi di record?

type TS1<'state, 'action> = { 
    actions : 'state -> #seq<'action> 
    move : 'state -> 'action -> 'state 
    state0 : 'state 
} 

Ma il tipo correttore non mi lascia:

.../stdin(2,29):error FS0715: Anonymous type variables are not permitted in this declaration 

Tuttavia, se dispiego la definizione di tipo flessibile, sto bene:

type TS2<'state, 'action, 'actions when 'actions :> seq<'action>> = { 
    actions : 'state -> 'actions 
    move : 'state -> 'action -> 'state 
    state0 : 'state 
} 

sono insoddisfatto dover aggiungere il tipo 'actions variabile rende il collegamento ai sistemi di transizione deterministici come oggetti matematici meno evidenti.

Non vedo cosa potrebbe andare storto consentendo tipi flessibili nelle definizioni dei record. È in qualche modo pericoloso? C'è un altro modo in cui potrei ottenere la chiarezza della definizione che vorrei?

Aggiornamento. Speravo di essere in grado di scrivere funzioni sui tipi di TS che sfruttano le implementazioni conosciute; cioè, voglio essere in grado di definire una funzione

let has_action a ts s = Set.contains a <| ts.actions s 

Questo ovviamente non digitare se il tipo dell'organo azioni è actions : 'state -> seq<'action>. Posso farlo con la seconda definizione, nel qual caso has_action ha tipo

has_action : a:'a -> ts:TS2<'s,'a,Set<'a>> -> s:'s -> bool when 'a : comparison 

Il tipo di questo esempio indica che il tipo flessibile in TS1 forse non aiuterebbe. Non c'è modo di evitare il disordinato parametro di terzo tipo in TS2? Mi sembra che l'esatta implementazione della raccolta di azioni per uno stato sia un dettaglio di implementazione che non dovrebbe essere esposto nel tipo.

+1

Compila per me, se si rimuove il '#' da prima il 'seq'. –

+0

@MarkPattison ha un buon punto: è più semplice rimuovere il '#' - perché pensi di averne bisogno? – Carsten

+0

riguardo al tuo aggiornamento IMO il terzo parametro è una parte vitale del tuo record quindi no non penso che dovresti liberartene qui (btw: non devi scriverlo - puoi usare '_' se invece tu Mi piace) - nel caso in cui tu voglia sapere (ma non sarà d'aiuto): l'unico posto dove puoi usare 'forall' quantificazione è su (interfaccia) membri (ho scritto su un problema simile qui: http: // gettingsharper. de/2014/09/29/church-numerals-net-and-working-around-the-value-restriction /) – Carsten

risposta

1

Questa è solo una limitazione dell'implementazione corrente del compilatore dei tipi consentiti di firme dei record. Per esempio, se si definisce il tipo nello stesso modo concettualmente, ma utilizzando un'interfaccia o una classe astratta invece di un record, si compila bene:

type TS1<'state, 'action> = 
    abstract actions : 'state -> #seq<'action> 
    abstract move : 'state -> 'action -> 'state 
    abstract state0 : 'state 
2

Hai praticamente risposto alla tua domanda qui ... La seconda opzione funziona, perché introduci un altro argomento di tipo, ovvero ti astraggo sopra 'actions. Il punto è che non è necessario definire valori generici in una definizione di record. Si consideri che la seconda opzione non è generica rispetto ai tipi, come sono definiti 'state e 'actions.

+0

Non sto seguendo abbastanza: una definizione di record è una definizione di tipo; Non sto definendo alcun valore. E non sono sicuro di cosa intendi con "la seconda opzione non è generica rispetto ai tipi"? –

+0

Intendo il seguente. Definendo un record, si sta definendo una classe (in termini IL/C#).Ora, se potessi definire i membri in un modo generico, lo renderesti immediatamente eterogeneo, poiché in ogni istanza di oggetto del tuo record avrebbe un diverso tipo di runtime. –

+0

Non sono sicuro se stiamo parlando di cosa sono, ma: non vedo il problema, poiché in quella prospettiva, voglio solo una classe adeguatamente generica. In realtà stavo solo sperando che il tipo flessibile introduca automaticamente una variabile di tipo per me. –