Pergunta

Eu estou tentando descobrir se Haskell usa dinâmico ou escopo estático. Eu percebo que, por exemplo, se você definir:

let x = 10

, em seguida, definir a função

let square x = x*x

Você tem 2 diferentes "X", e isso significa que ele tem como escopo dinamicamente? Se não, o escopo ele usa, e por quê?

Além disso, pode variáveis ??Haskell tem aliases (um nome diferente para o mesmo local de memória / valor)?

Graças.

Foi útil?

Solução

Há algumas coisas erradas em suas declarações ...

  • Não há variáveis ??mutáveis ??em Haskell apenas definições (ou variáveis ??imutáveis)
  • A posição de memória variável é um conceito que não existem em Haskell

No seu exemplo, x é não 10 na função é apenas um argumento para quadrado, que pode assumir qualquer valor (você pode especificar o tipo mais tarde) neste caso 10, mas apenas neste caso.

Aqui está um exemplo de aliases fornecidos pelo 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

Outras dicas

Haskell uso (em termos gerais) exatamente o mesmo escopo lexical como a maioria das outras línguas.

por exemplo.

x = 10

Os resultados em um valor referenciado por meio x no escopo global, enquanto

square x = x * x

resultará na x sendo escopo léxico para a praça função. Pode ajudar se você acha da forma acima sendo uma minúcia sintático para:

square = \ x -> x * x

Quanto à sua outra pergunta eu não tenho certeza do que você quer dizer com aliasing

Respondendo apenas a segunda parte da pergunta:

Você pode ter vários aliases para o mesmo "local de memória", mas desde que todos eles são imutáveis, não importa a maior parte do tempo.

exemplo mudo:

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

Quando dentro foo chamado a partir bar, tanto x e y são claramente o mesmo valor. Mas desde que você não pode modificar qualquer x ou y, você nem vai notar.

Como a primeira parte da pergunta já foi respondida por outros, aqui é a segunda parte:

Eu assumo por aliasing você quer dizer one name for another. Como Haskell é uma linguagem funcional, e as funções se comportam como identificadores normais em qualquer caso, você pode fazer isso como este:

y = x

que definiria uma y alias para o x função. Note-se que tudo é uma função. Mesmo que ele se parece com um "variável" , é apenas uma função nullary levando sem argumentos. Aliases para tipos parecido com este:

type Function = Double -> Double

que definiria uma Function alias para o tipo Double -> Double

Haskell usa escopos aninhados estáticos. O que é um pouco confuso em comparação com outras línguas que têm escopos aninhados estáticos é que o escopo de um nome é um bloco que inclui testes anteriores a sua definição . Por exemplo

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

aqui o nome de 'odds' está no escopo na definição de 'Evens', apesar do fato surpreendente que 'odds' ainda não foi definido. (O exemplo define duas listas infinitas de números pares e ímpares.)

A língua morta com uma regra de escopo semelhante foi Modula-3. Mas Haskell é um complicado bit, em que você pode tentar 'redefinir' uma variável dentro do mesmo alcance, mas em vez disso você simplesmente introduzir uma outra equação recursão. Esta é uma armadilha para as pessoas que aprenderam ML ou Esquema primeiro:

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

Isto é perfeitamente bom ML ou Esquema deixar *, mas Haskel tem esquema letrec semântica, sem a restrição de valores lambda. Não admira que este é um assunto complicado!

No seu exemplo, a definição global de x é sombreado pela definição local de x. Em Haskell, o escopo de uma variável é determinado por uma leitura estática do código-fonte - isso é chamado de escopo léxico, mas pode obter algo semelhante ao escopo dinâmico com parâmetros implícitos (mas que pode levar a um comportamento inesperado (que eu li, nunca tentou 'em mim mesmo)).

Para resumir as outras respostas de forma concisa:

  1. escopo léxico
  2. aliasing é tão fácil como x = 1; y = x mas, normalmente, não importa, porque as coisas são imutáveis.

O let sintaxe que você usar no seu exemplo parece que está no ghci> interativo alerta. Tudo no modo interativo ocorre dentro do IO mônada assim que as coisas podem aparecer mais mutável lá do que normal.

Bem, como eu acho que as pessoas já disse, Haskell não tem nenhum variáveis ??como encontrado na maioria das outras línguas, ele só tem expressões. No seu exemplo let x = 10 x é uma expressão que sempre avalia a 10. Você não pode realmente mudar o valor de x, mais tarde, que você pode usar as regras de escopo para escondê-lo através da definição de x para ser outra expressão.

Sim, Haskell tem aliases. Experimente este pequeno programa:

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top