Esta é uma transformação que o GHC pode fazer: "Eu sou o compilador que opera por si mesmo, e todos os _ | _s são iguais a mim". Você está pedindo os detalhes de implementação que fazem com que essas duas linhas sejam compiladas de maneira diferente?
shachaf de
3
erroré especial e não é realmente um mecanismo de exceção. Para exceções reais e captáveis, consulte a Errormônada.
Cat Plus Plus
1
Observe, por exemplo, que (\f g x -> f (g x)) error error ""se comporta de maneira diferente de (.) error error "", embora essa função seja equivalente a (.). Talvez tenha a ver com os sinalizadores de otimização com os quais o Prelude foi compilado.
shachaf
5
Também iterate error "" !! ne o incrível fix error.
Vitus
9
Eu sempre finjo isso error = errore programo de acordo.
Gabriel Gonzalez
Respostas:
101
A resposta é que esta é a (um tanto surpreendente) semântica de exceções imprecisas
Quando o código puro pode ser mostrado para avaliar um conjunto de valores excepcionais (ou seja, o valor de errorou undefined, e explicitamente não o tipo de exceções geradas em IO ), então a linguagem permite que qualquer valor desse conjunto seja retornado. Valores excepcionais em Haskell são mais parecidos NaNcom código de ponto flutuante, em vez de exceções baseadas em fluxo de controle em linguagens imperativas.
Uma pegadinha ocasional, mesmo para Haskellers avançados, é um caso como:
case x of1 -> error "One"
_ -> error "Not one"
Uma vez que o código avalia um conjunto de exceções, o GHC é livre para escolher uma. Com as otimizações ativadas, você pode descobrir que isso sempre é avaliado como "Nenhum".
porque nós fazemos isso? Caso contrário, restringiríamos excessivamente a ordem de avaliação da linguagem, por exemplo, teríamos que fixar um resultado determinístico para:
f (error "a") (error "b")
exigindo, por exemplo, que seja avaliado da esquerda para a direita se houver valores de erro. Muito pouco Haskelly!
Como não queremos prejudicar as otimizações que podem ser feitas em nosso código apenas para dar suporte error, a solução é especificar que o resultado é uma escolha não determinística do conjunto de valores excepcionais: exceções imprecisas! De certa forma, todas as exceções são retornadas e uma é escolhida.
Normalmente, você não se importa - uma exceção é uma exceção - a menos que você se preocupe com a string dentro da exceção, caso em que usar errorpara depurar é altamente confuso.
Referências: Uma semântica para exceções imprecisas , Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Projeto e implementação de linguagens de programação Proc (PLDI'99), Atlanta. ( PDF )
Eu entendo que o GHC escolheu uma das exceções que podem ser encontradas. Mas no seu exemplo de "caso", a exceção "Não um" não pode ser encontrada para uma entrada de 1, então ainda classificaria isso como um bug.
Peaker
8
@Peaker dead code elim - o otimizador não precisa olhar para x para ver que um erro é o resultado, todos os ramos produzem o "mesmo" valor, então ele pode ignorar o valor de entrada completamente. Não é um bug, sob exceções imprecisas!
Don Stewart
1
@lpsmith: Acho que todos os tipos de exceção são imprecisos (quando lançados usando throw) e com os quais você pode lançar uma exceção de forma determinística throwIO.
FunctorSalad de
4
@Peaker Acho que você está certo. Não acho que o ghc deva otimizar essa expressão se quiser jogar pelas regras estabelecidas no papel de exceções imprecisas.
agosto às 9h29
3
Qual o papel exceções imprecisas não parecem dizer é que se o scrutinee caso é um valor de erro, então os valores de erro dos galhos pode ser devolvido. Então, case error "banana" of (x:xs) -> error "bonobo"pode dar a você * Exception: bonobo.
error
é especial e não é realmente um mecanismo de exceção. Para exceções reais e captáveis, consulte aError
mônada.(\f g x -> f (g x)) error error ""
se comporta de maneira diferente de(.) error error ""
, embora essa função seja equivalente a(.)
. Talvez tenha a ver com os sinalizadores de otimização com os quais o Prelude foi compilado.iterate error "" !! n
e o incrívelfix error
.error = error
e programo de acordo.Respostas:
A resposta é que esta é a (um tanto surpreendente) semântica de exceções imprecisas
Quando o código puro pode ser mostrado para avaliar um conjunto de valores excepcionais (ou seja, o valor de
error
ouundefined
, e explicitamente não o tipo de exceções geradas em IO ), então a linguagem permite que qualquer valor desse conjunto seja retornado. Valores excepcionais em Haskell são mais parecidosNaN
com código de ponto flutuante, em vez de exceções baseadas em fluxo de controle em linguagens imperativas.Uma pegadinha ocasional, mesmo para Haskellers avançados, é um caso como:
case x of 1 -> error "One" _ -> error "Not one"
Uma vez que o código avalia um conjunto de exceções, o GHC é livre para escolher uma. Com as otimizações ativadas, você pode descobrir que isso sempre é avaliado como "Nenhum".
porque nós fazemos isso? Caso contrário, restringiríamos excessivamente a ordem de avaliação da linguagem, por exemplo, teríamos que fixar um resultado determinístico para:
f (error "a") (error "b")
exigindo, por exemplo, que seja avaliado da esquerda para a direita se houver valores de erro. Muito pouco Haskelly!
Como não queremos prejudicar as otimizações que podem ser feitas em nosso código apenas para dar suporte
error
, a solução é especificar que o resultado é uma escolha não determinística do conjunto de valores excepcionais: exceções imprecisas! De certa forma, todas as exceções são retornadas e uma é escolhida.Normalmente, você não se importa - uma exceção é uma exceção - a menos que você se preocupe com a string dentro da exceção, caso em que usar
error
para depurar é altamente confuso.Referências: Uma semântica para exceções imprecisas , Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Projeto e implementação de linguagens de programação Proc (PLDI'99), Atlanta. ( PDF )
fonte
throw
) e com os quais você pode lançar uma exceção de forma determinísticathrowIO
.case error "banana" of (x:xs) -> error "bonobo"
pode dar a você* Exception: bonobo
.