A linearidade não é uma restrição suficiente para definir uma representação com estado única e, portanto, a resposta à sua pergunta depende de como você interpreta a lógica linear em termos de estado. Isso normalmente será refletido em como você deve interpretar o modalidade.! UMA
Se a semântica pretendida das referências disser que todos os ponteiros são valores únicos (ou seja, existe no máximo uma única referência a um objeto), os dags e as estruturas gráficas não são expressáveis, pelo tipo de razão tautológica em que um dag pode conter várias referências a o mesmo objeto. Nesse caso deve ser um cálculo que cria um novo valor do tipo A , desde que você quer mapas δ A : ! A ⊸ ! A ⊗ ! Um e ε A : ! A ⊸ A! UMAUMAδUMA: ! A ⊸ ! A ⊗ ! UMAϵUMA: ! A ⊸ A .
No entanto, suponha que você queira para representar o compartilhamento . Então, os objectos podem ser com a contagem de referência recolhidos-lixo, com os mapas ô Um : ! A ⊸ ! A ⊗ ! Um e ε A : ! A ⊸ A pode ser realizado como operações que apenas aumentam as contagens de referência. Nesse caso, você não pode usar a linearidade para assumir que é sempre seguro alterar valores, já que há compartilhamento. Mas você pode garantir que toda a alocação de memória seja explícita no seu programa e que não haja ciclos no heap.! UMAδUMA: ! A ⊸ ! A ⊗ ! UMAϵUMA: ! A ⊸ A
A maioria das implementações práticas de tipos lineares não usa nenhuma dessas duas interpretações. Em vez disso, as referências são vistas como entidades livremente duplicáveis, e o que rastreamos linearmente são de fato recursos . Recursos não são valores de tempo de execução; elas são entidades puramente conceituais, destinadas a representar a permissão para acessar uma referência. A idéia é que você programe em um estilo de passagem de permissão e, mesmo que haja muitas referências ao mesmo objeto, uma leitura ou modificação de um pedaço de estado só poderá ocorrer se você também tiver a capacidade de acessá-lo. E como a capacidade é linear, você sabe que somente você pode alterá-la.
n e wg e ts e tc o p y::::∀ α .α ⊸ ∃ c : ι . c um p ( c ) ⊗ r e f( α , c )∀ α , c : ι .c um p (c)⊗ r e f( Α , c ) ⊸ α ⊗ c um p ( c ) ⊗ r e f( α , c )∀ α , c : ι .c um p (c)⊗ r e f( Α , c ) ⊗ α ⊸ c um p ( c ) ⊗ r e f( α , c )∀ α , c : ι .r e f( Α , c ) ⊸ r e f(α,c)⊗ref(α,c)
Na API esboçada acima, varia sobre ι , algum domínio de índices em tempo de compilação e α varia sobre tipos. Temos um tipo c a p ( c ), que é uma capacidade indexada por c , e um tipo r e f ( α , c ) , que é um tipo de referência a α acessada por uma capacidade c . Chamar g de e t e s e t em uma referência requer a capacidade C , e ligando n ecιαc a p (c)cr e f( α , c )αcg e ts e tc cria uma nova referência e um novo recurso que compartilha um índice comum. No entanto, c o p y ing uma referência não requer acesso a qualquer recurso, para que qualquer pessoa pode copiar uma referência, desde que eles não olhar para ele.n e wc o p y