A semântica de um programa é um modelo de comportamento que, como qualquer modelo científico, ignora aspectos que você não deseja estudar.
Um modelo extremamente detalhado da execução de um programa modelaria o comportamento físico do computador que o executa, incluindo o tempo de execução, consumo de energia, radiação eletromagnética etc. Esses aspectos raramente são levados em consideração, porque raramente são relevantes. No entanto, às vezes são importantes: um modelo útil de piloto automático de avião precisa incluir informações de tempo de execução, um modelo útil de segurança de um cartão de crédito precisa incluir radiação eletromagnética, ...
Na semântica típica, efeitos colaterais como tempo e consumo de energia são ignorados. Mesmo se em uma configuração mundana em que você digita uma expressão em um prompt de intérprete Haskell, a impressão do resultado é um efeito colateral (se você tentar imprimir um objeto infinito, isso importa). Se o intérprete Haskell ficar sem memória, esse também será um efeito colateral observável em um modelo do “mundo real”, mas não em um modelo idealizado de Haskell que efetivamente permita cálculos ilimitados.
Um efeito colateral observável é aquele modelado na semântica. Em modelos típicos de linguagens de programação, o consumo de memória não é modelado; portanto, um cálculo que requer 1 TB de armazenamento pode ser puro, mesmo que, se você tentar executá-lo no seu PC, ele falhará notavelmente.
Outro tipo de efeito colateral não observável é o interno da função. Acho que é isso que a maioria dos semanticistas pensaria ao falar sobre efeitos colaterais não observáveis. Considere um cálculo que usa dados mutáveis internamente, mas não compartilha esses dados mutáveis com nenhuma outra parte do programa. Por exemplo, uma função de classificação de lista que constrói uma matriz com os mesmos elementos da lista, classifica a matriz no local e retorna uma lista contendo os elementos como a matriz em sua ordem final: um modelo semântico de subexpressões dessa função exibe lado efeitos (modificações da matriz), mas a função em si não tem efeito colateral externo, portanto é pura.
Para um exemplo mais sutil, considere uma função que grava alguns dados em um arquivo temporário e limpa depois de si próprio. Em uma semântica em que sempre há espaço suficiente para arquivos e programas temporários que não compartilham arquivos temporários, a função não tem efeito colateral; o arquivo temporário atua como memória extra usada pela função. Em uma semântica que leva em consideração todas as condições do sistema de arquivos, a função tem um efeito colateral - pode falhar devido a circunstâncias externas. Em uma semântica que permite à máquina travar, a função tem um efeito colateral: se houver uma falha durante a execução da função, o arquivo temporário poderá ser deixado para trás. Em uma semântica que permite que programas executados simultaneamente vejam e talvez modifiquem o arquivo temporário, a função tem um efeito colateral.