Pergunta

me deparei com a seguinte definição como eu tentar aprender Haskell usando um projeto real para dirigi-lo. Eu não entendo o que o ponto de exclamação na frente de cada meio de argumentos e os meus livros não parecia mencioná-lo.

data MidiMessage = MidiMessage !Int !MidiMessage
Foi útil?

Solução

É uma declaração rigor. Basicamente, isso significa que ele deve ser avaliado para o que é chamado "Formulário de cabeça normais fraco" quando o valor de estrutura de dados é criado. Vamos olhar um exemplo, para que possamos ver o que isto significa:

data Foo = Foo Int Int !Int !(Maybe Int)

f = Foo (2+2) (3+3) (4+4) (Just (5+5))

A função f acima, quando avaliadas, irá retornar uma "conversão": isto é, o código para executar para descobrir o seu valor. Nesse ponto, um Foo nem sequer existe ainda, apenas o código.

Mas em algum momento alguém pode tentar olhar dentro dele, provavelmente através de um jogo padrão:

case f of
     Foo 0 _ _ _ -> "first arg is zero"
     _           -> "first arge is something else"

Este vai executar código suficiente para fazer o que precisa, e nada mais. Por isso vai criar uma Foo com quatro parâmetros (porque você não pode olhar dentro dele sem ela existente). O primeiro, já que estamos testando isso, precisamos avaliar todo o caminho até 4, onde percebemos que não corresponde.

O segundo não precisa ser avaliada, porque não estamos testando-o. Assim, ao invés de 6 sendo armazenado nessa localização de memória, vamos armazenar o código para uma possível avaliação posterior, (3+3). Isso vai se transformar em um 6 apenas se alguém olha para ele.

O terceiro parâmetro, no entanto, tem um ! na frente dele, então é estritamente avaliadas:. (4+4) é executado, e 8 é armazenado nessa localização de memória

O quarto parâmetro também é avaliada rigorosamente. Mas aqui é onde fica um pouco complicado: estamos avaliando não totalmente, mas apenas a forma de cabeça normais fraco. Isto significa que nós descobrir se é Nothing ou Just alguma coisa, e armazenar isso, mas nós não ir mais longe. Isso significa que nós não armazenam Just 10 mas na verdade Just (5+5), deixando a conversão interior não avaliada. Isso é importante saber, embora eu acho que todas as implicações desse movimento, em vez fora do âmbito desta questão.

Você pode anotar os argumentos da função, da mesma forma, se você ativar a extensão da linguagem BangPatterns:

f x !y = x*y

f (1+1) (2+2) retornará o (1+1)*4 conversão.

Outras dicas

Uma simples maneira de ver a diferença entre rígidas e não-rígidas argumentos do construtor é como eles se comportam quando são indefinido. Dada

data Foo = Foo Int !Int

first (Foo x _) = x
second (Foo _ y) = y

Uma vez que o argumento não-estrita não é avaliado por second, passando undefined não causa um problema:

> second (Foo undefined 1)
1

Mas o argumento rigoroso não pode ser undefined, mesmo se não usar o valor:

> first (Foo 1 undefined)
*** Exception: Prelude.undefined

Eu acredito que é uma anotação de rigor.

Haskell é uma pura e preguiçoso linguagem funcional, mas às vezes a sobrecarga de preguiça pode ser muito ou desperdício. Então, para lidar com isso, você pode pedir para compilador para avaliar plenamente os argumentos para uma função em vez de analisar thunks ao redor.

Não há mais informações sobre esta página:. Performance / Strictness

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top