Domanda

Sto cercando di capire se Haskell utilizza l'ambito dinamico o statico. Mi rendo conto che, ad esempio, se si definisce:

let x = 10

quindi definire la funzione

let square x = x*x

Hai 2 diversi "quotazioni", e questo significa che ha un ambito dinamico? In caso contrario, quale ambito viene utilizzato e perché?

Inoltre, le variabili Haskell possono avere alias (un nome diverso per la stessa posizione / valore di memoria)?

Grazie.

È stato utile?

Soluzione

Ci sono alcune cose che non vanno nelle tue dichiarazioni ...

  • Non ci sono variabili mutabili in Haskell solo definizioni (o variabili immutabili)
  • Una posizione di memoria variabile è un concetto che non esiste in Haskell

Nel tuo esempio, x è non 10 nella funzione è solo un argomento da quadrare, che può assumere qualsiasi valore (puoi specificare il tipo in seguito) in questo caso 10, ma solo in questo caso.

Ecco un esempio di alias fornito da Curt Sampson :

import Data.IORef

main :: IO ()
main = do x <- newIORef 0         -- write 0 into x
          readIORef x >>= print   -- x contains 0
          let y = x
          readIORef y >>= print   -- y contains 0
          writeIORef x 42         -- write 42 into x
          readIORef y >>= print   -- y contains 42

Altri suggerimenti

Haskell usa (in generale) esattamente lo stesso ambito lessicale della maggior parte delle altre lingue.

ad es.

x = 10

Risultati in un valore a cui si fa riferimento tramite x nell'ambito globale, mentre

square x = x * x

si tradurrà in x in ambito lessicale al riquadro delle funzioni. Può essere utile se ritieni che il modulo sopra sia una gentilezza sintattica per:

square = \ x -> x * x

Per quanto riguarda l'altra tua domanda, non sono sicuro di cosa intendi per aliasing

Rispondere solo alla seconda parte della domanda:

Puoi avere diversi alias per la stessa "posizione di memoria", ma poiché sono tutti immutabili, non importa la maggior parte delle volte.

Esempio stupido:

foo x y = x * y
bar z = foo z z

All'interno di foo chiamato da bar , sia x che y hanno chiaramente lo stesso valore. Ma poiché non puoi modificare x o y , non te ne accorgerai nemmeno.

Poiché la prima parte della domanda ha già ricevuto risposta da altri, ecco la seconda parte:

Suppongo che aliasing intendi un nome per un altro . Poiché haskell è un linguaggio funzionale e le funzioni si comportano come normali identificatori in ogni caso, puoi farlo in questo modo:

y = x

che definirebbe un alias y per la funzione x . Si noti che tutto è una funzione. Anche se sembra una " variabile " , è solo una funzione null che non accetta argomenti. Gli alias per i tipi si presentano così:

type Function = Double -> Double

che definirebbe un alias Function per il tipo Double - > Doppio

Haskell utilizza ambiti nidificati statici. Ciò che è un po 'confuso rispetto ad altre lingue che hanno ambiti nidificati statici è che l'ambito di un nome è un blocco che include test che precedono la sua definizione . Ad esempio

evens = 0 : map (+1) odds
odds  = map : (+1) evens

qui il nome "probabilità" rientra nella definizione di "pari", nonostante il fatto sorprendente che "probabilità" non sia ancora stato definito. (L'esempio definisce due elenchi infiniti di numeri pari e dispari.)

Una lingua morta con una regola di scoping simile era Modula-3. Ma Haskell è un po 'più complicato in quanto puoi tentare di' ridefinire 'una variabile all'interno dello stesso ambito ma invece devi semplicemente introdurre un'altra equazione di ricorsione. Questa è una trappola per le persone che hanno imparato prima ML o Scheme:

let x = 2 * n
    x = x + 1   -- watch out!

Questo è perfettamente buono ML o Schema let *, ma Haskel ha schema semantica letrec, senza la restrizione ai valori lambda. Non c'è da stupirsi che questa sia roba complicata!

Nel tuo esempio, la definizione globale di x è ombreggiata dalla definizione locale di x. In Haskell, l'ambito di una variabile è determinato da una lettura statica del codice sorgente - questo si chiama ambito lessicale, ma può ottenere qualcosa di simile allo scoping dinamico con parametri impliciti (ma ciò può portare a comportamenti imprevisti (ho letto; mai ho provato io stesso)).

Per riassumere le altre risposte in modo conciso:

  1. ambito lessicale
  2. l'aliasing è facile come x = 1; y = x ma di solito non importa perché le cose sono immutabili.

La sintassi let che usi nel tuo esempio sembra che sia al prompt interattivo ghci > . Tutto in modalità interattiva avviene all'interno della monade IO, quindi le cose possono apparire più mutevoli del normale.

Beh, come penso che la gente abbia già detto, Haskell non ha alcuna variabile come si trova nella maggior parte delle altre lingue, ha solo espressioni. Nel tuo esempio let x = 10 x è un'espressione che valuta sempre 10. 10. In realtà non puoi cambiare il valore di x in seguito, sebbene puoi usare le regole di scoping per nasconderlo definendo x essere un'altra espressione.

Sì, Haskell ha alias. Prova questo piccolo programma:

import Data.IORef

main :: IO ()
main = do x <- newIORef 0         -- write 0 into x
          readIORef x >>= print   -- x contains 0
          let y = x
          readIORef y >>= print   -- y contains 0
          writeIORef x 42         -- write 42 into x
          readIORef y >>= print   -- y contains 42
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top