2013-02-03 5 views
8

non posso per la vita di me capire perché la seguente funzione SML sta gettando un avvertimento nel mio problema compiti:SML Attenzione: Tipo Vars Non generalizzate quando si utilizzano liste vuote o opzione NONE

fun my_func f ls = 
    case ls of 
    [] => raise MyException 
    | head :: rest => case f head of 
        SOME v => v 
        | NONE => my_func f rest 

fun f a = if isSome a then a else NONE; 

Ogni volta chiamo my_func con le seguenti funzioni di test:

my_func f [NONE, NONE]; 
my_func f []; 

ho sempre trovato l'avvertimento:

guerra Ning: tipo non Le variabili di generalizzato a causa della restrizione value sono istanziate ai tipi fittizi (X1, X2, ...)

Ogni volta che passo in un elenco di opzioni contenente almeno un certo valore, questo avviso non è gettato. So che deve essere qualcosa a che fare con il fatto che sto usando il polimorfismo nella mia funzione di curry, ma sono rimasto completamente bloccato su come sbarazzarmi di questi avvertimenti.

Si prega di aiutare se avete qualche idea - grazie in anticipo!

risposta

17

La restrizione valore fa riferimento nel avviso è una delle cose più complicato da capire in SML, ma farò del mio meglio per spiegare il motivo per cui si tratta in questo caso e cercare di puntare verso alcune risorse per imparare Di Più.

Come sapete, SML utilizzerà l'inferenza di tipo per dedurre la maggior parte dei tipi nei vostri programmi. In questo programma, il tipo di my_func sarà dedotto per essere ('a -> 'b option) -> 'a list -> 'b. Come hai notato, è un tipo polimorfico. Quando si chiama my_func come questo

myfunc f [NONE, SOME 1, NONE]; 

... le variabili di tipo 'a e 'b sono istanziati per int option e int.

Tuttavia quando lo si chiama, senza un valore come SOME 1 sopra

myfunc f [NONE, NONE]; 

Cosa pensi delle variabili di tipo dovrebbero essere istanziati a? I tipi devono essere polimorfici, ad esempio 't option e 't per tutti i tipi 't. Tuttavia, esiste una limitazione che impedisce a valori come questo di assumere tipi polimorfici.

SML definisce alcune espressioni come valori non espansivi e solo questi valori possono assumere tipi polimorfici.Essi sono:

  • letterali (costanti)
  • variabili
  • funzione espressioni
  • costruttori (ad eccezione di ref) applicato ai valori non espansive
  • a valori non espansive con un tipo di annotazione
  • tuple in cui ogni campo è un valore non espansivo
  • record in cui ogni campo è un valore non espansivo
  • liste in cui ogni campo è un valore non espansiva

tutte le altre espressioni, in particolare chiamate di funzione (che è ciò che la chiamata a my_func è) non può essere polimorfico. Neanche i riferimenti. Si potrebbe essere curioso di vedere che quanto segue non solleva un avvertimento:

fn() => my_func f [NONE, NONE]; 

Invece, il tipo dedotto è unit -> 'a. Se dovessi chiamare questa funzione, avresti di nuovo l'avviso.

La mia comprensione del motivo di questa restrizione è un po 'debole, ma credo che il problema di root sottostante sia un riferimento mutabile. Ecco un esempio che ho preso dal sito MLton link sottostante:

val r: 'a option ref = ref NONE 
val r1: string option ref = r 
val r2: int option ref = r 
val() = r1 := SOME "foo" 
val v: int = valOf (!r2) 

Questo programma non TYPECHECK sotto SML, a causa della limitazione del valore. Se non fosse per la restrizione del valore, questo programma avrebbe un errore di tipo in fase di esecuzione.

Come ho detto, la mia comprensione è traballante. Tuttavia spero di aver gettato un po 'di luce sul problema che hai incontrato, anche se credo che nel tuo caso potresti tranquillamente ignorare l'avviso. Qui ci sono alcuni riferimenti dovrebbero decidere vuoi scavare più a fondo:

http://users.cis.fiu.edu/~smithg/cop4555/valrestr.html

http://mlton.org/ValueRestriction

(BTW il sito MLton è oro massiccio C'è così tanto nascosto qui, quindi se si. Stai cercando di capire qualcosa di strano su SML, ti consiglio vivamente di cercare qui perché probabilmente aumenterai molto di più di quanto inizialmente volevi)

Poiché sembra che tu stia effettivamente utilizzando SML/NJ, questo è un guida abbastanza utile per l'er messaggi ror e gli avvisi che vi darà al momento della compilazione:

http://flint.cs.yale.edu/cs421/smlnj/doc/errors.html

+0

La ringrazio molto per la risposta informata! Analizzerò le risorse suggerite per ulteriori ricerche e riferirò se trovo un modo per risolvere questo messaggio di avviso. Come hai detto, potrebbe non essere possibile per quei determinati casi di test che sono vuoti o contengono semplicemente NONE, a causa della loro natura polimorfica. Grazie ancora per il vostro aiuto. – mbear

+0

Nessun problema, felice di poterti aiutare.Un paio di cose che puoi fare per rimuovere l'avviso è (1) annotare con qualsiasi tipo, il che rende il valore non più polimorfico ovviamente: '(my_func f [NONE, NONE]): int' o (2) rendi conto solo di questo avviso si verifica quando si immette un valore come questo in REPL e probabilmente non verrà generato in un programma più grande che chiama 'my_func' con altri dati. – spacemanaki

+1

Haskell ha una versione di questa stranezza, o la mancanza di riferimenti mutabili la sta salvando? –

Problemi correlati