Una domanda sui tipi statici

3

Come si scrive staticamente il seguente programma JavaScript

function c(str) {
  c = eval(str);
  return c(str);
}

Non sto cercando di iniziare una guerra di fiamma, ma sono sinceramente curioso. Ho sempre pensato che i linguaggi dinamici permettessero di scrivere più programmi a causa di esempi come quelli sopra. Ma se un linguaggio tipizzato in modo statico è completo di Turing, dovrebbe essere in grado di esprimere l'equivalente del programma di cui sopra. Quindi, dove esattamente il mio ragionamento si interrompe perché questo mi sembra paradossale? Il mio ragionamento è che questa è ovviamente una funzione che non può essere digitata in un linguaggio tipizzato in modo statico e consente comunque la generalità consentita dal codice precedente.

    
posta davidk01 01.08.2014 - 17:12
fonte

1 risposta

9

Ci sono alcuni modi per procedere digitando questo.

Dimentica tutti i tipi!

Puoi imitare i tipi dinamici in linguaggi tipizzati in modo statico semplicemente dimenticando che avevi tipi in primo luogo e passando a utilizzare le informazioni sul tipo di runtime.

In haskell questo sarebbe simile a

evalThingy s = let result = eval s
                   resultTy = typeOf result
               if resultTy == typeOf (id :: String -> String)
               then unsafeCoerce result s
               else fail in some manner

Quindi abbiamo un interruttore di runtime che controlla solo se è sicuro continuare e se lo è, battere il tipografo in sottomissione e procedere.

Personalmente non mi piace in questo modo, perché se dovessi scrivere qualcosa in un sistema di tipo statico, voglio ottenere i benefici per la sicurezza. Ciò significa che le coercizioni come sopra sono un no-no.

Errore esplicito

Il più semplice è forzare eval a restituire un tipo specifico o fallire in modo controllato

eval : String -> Either Error a

E quindi potremmo dire qualcosa di simile

 c = eval(str) : Either Error (str -> Int)
 case c of
   Right f -> f str
   Left err -> blowup str

Per supportare questo bene, il linguaggio ha bisogno di qualcosa chiamato polimorfismo di tipo [parametrico] di ritorno. ATM Sono consapevole solo del fatto che sia supportato dalle classi di tipi. Ciò significa che abbiamo bisogno di cose diverse a seconda di come è chiamato il tipo.

Tipi di dipendenti

L'approccio più contorto sarebbe quello di riflettere effettivamente il giudizio di battitura della lingua in una funzione, diciamo typeOf .

typeOf : String -> TypeOfTypes

Dove TypeOfTypes è l'universo di tutti i tipi che i programmi normalmente usano. Questo non può includere se stesso se vogliamo un po 'di sanità mentale nel nostro sistema di tipi.

Successivamente possiamo assegnare eval un tipo dipendente abbastanza complesso a eval

eval : (s : str) -> typeOf str

applySelf : (s : String) -> typeOf s = (String -> String) -> String
applySelf = function(s, p){
  case p of
    reflexivity -> eval(s)(s)
}

Quindi forziamo il chiamante di applySelf a dimostrare che la stringa che ci chiedono di valutare avrà il tipo string -> string a quel punto possiamo ignorare i controlli di sicurezza poiché abbiamo una prova di correttezza statica.

    
risposta data 01.08.2014 - 17:20
fonte

Leggi altre domande sui tag