Me deparei com a seguinte definição ao tentar aprender Haskell usando um projeto real para conduzi-lo. Não entendo o que o ponto de exclamação na frente de cada argumento significa e meus livros não pareciam mencioná-lo.
data MidiMessage = MidiMessage !Int !MidiMessage
haskell
syntax
lazy-evaluation
David
fonte
fonte
Respostas:
É uma declaração de rigor. Basicamente, isso significa que ele deve ser avaliado para o que é chamado "formulário normal de cabeça fraca" quando o valor da estrutura de dados é criado. Vejamos um exemplo, para que possamos ver exatamente o que isso significa:
A função
f
acima, quando avaliada, retornará um "thunk": ou seja, o código a ser executado para descobrir seu valor. Nesse ponto, um Foo ainda nem existe, apenas o código.Mas em algum momento alguém pode tentar olhar dentro dele, provavelmente através de uma correspondência de padrões:
Isso vai executar código suficiente para fazer o que precisa, e não mais. Portanto, ele criará um Foo com quatro parâmetros (porque você não pode olhar dentro dele sem que ele exista). A primeira, como estamos testando, precisamos avaliar todo o caminho para
4
em que percebemos que não corresponde.O segundo não precisa ser avaliado, porque não estamos testando. Portanto, em vez de
6
ser armazenado nesse local de memória, apenas armazenaremos o código para uma possível avaliação posterior(3+3)
. Isso só se tornará um 6 se alguém olhar para ele.O terceiro parâmetro, no entanto, tem um
!
na frente, portanto é estritamente avaliado:(4+4)
é executado e8
é armazenado nesse local de memória.O quarto parâmetro também é rigorosamente avaliado. Mas aqui é onde fica um pouco complicado: estamos avaliando não totalmente, mas apenas a forma normal da cabeça fraca. Isso significa que descobrimos se é
Nothing
ouJust
algo assim e armazenamos isso, mas não vamos mais longe. Isso significa que não armazenamos,Just 10
masJust (5+5)
, na verdade , deixando o thunk dentro de uma avaliação. É importante saber, embora eu pense que todas as implicações disso vão além do escopo desta questão.Você pode anotar argumentos de função da mesma maneira, se ativar a
BangPatterns
extensão de idioma:f (1+1) (2+2)
retornará o thunk(1+1)*4
.fonte
seq
.Uma maneira simples de ver a diferença entre argumentos estritos e não estritos do construtor é como eles se comportam quando são indefinidos. Dado
Como o argumento não estrito não é avaliado
second
, a transferênciaundefined
não causa um problema:Mas o argumento estrito não pode ser
undefined
, mesmo se não usarmos o valor:fonte
!
símbolo possui, em vez de se aprofundar nos detalhes internos da implementação.Eu acredito que é uma anotação de rigor.
Haskell é uma linguagem funcional pura e preguiçosa , mas às vezes a sobrecarga da preguiça pode ser muito ou um desperdício. Portanto, para lidar com isso, você pode pedir ao compilador para avaliar completamente os argumentos de uma função em vez de analisar os thunks.
Há mais informações nesta página: Desempenho / Rigor .
fonte
map Just [1,2,3]
para obter [Apenas 1, Apenas 2, Apenas 3]) e assim por diante. Acho útil pensar na capacidade de combinar padrões com eles, bem como em uma instalação completamente não relacionada.