La sémantique d'un programme est un modèle de son comportement qui, comme tout modèle scientifique, ignore les aspects que vous ne souhaitez pas étudier.
Un modèle extrêmement détaillé de l'exécution d'un programme modéliserait le comportement physique de l'ordinateur qui l'exécute, y compris le temps d'exécution, la consommation électrique, le rayonnement électromagnétique, etc. De tels aspects sont très rarement pris en compte car ils sont très rarement pertinents. Néanmoins, ils importent parfois: un modèle utile de pilote automatique d'avion doit inclure des informations sur l'exécution, un modèle utile de sécurité d'une carte de crédit doit inclure des rayonnements électromagnétiques, ...
Dans la sémantique typique, les effets secondaires tels que le timing et la consommation d'énergie sont ignorés. Même si dans un cadre banal où vous tapez une expression à l'invite d'un interpréteur Haskell, l'impression du résultat est un effet secondaire (si vous essayez d'imprimer un objet infini, cela compte). Si l'interpréteur Haskell manque de mémoire, c'est également un effet secondaire observable dans un modèle «réel», mais pas dans un modèle idéalisé de Haskell qui permet effectivement des calculs illimités.
Un effet secondaire observable est celui qui est modélisé dans la sémantique. Dans les modèles typiques de langages de programmation, la consommation de mémoire n'est pas modélisée, donc un calcul qui nécessite 1 To de stockage peut être pur, même si si vous essayez de l'exécuter sur votre PC, il échouerait.
Un autre type d'effet secondaire non observable est interne à la fonction. C'est, je pense, ce que la plupart des sémantistes penseraient en parlant d'effets secondaires non observables. Considérons un calcul qui utilise des données mutables en interne, mais ne partage ces données mutables avec aucune autre partie du programme. Par exemple, une fonction de tri de liste qui construit un tableau avec les mêmes éléments que la liste, trie le tableau en place et renvoie une liste contenant les éléments sous forme de tableau dans leur ordre final: un modèle sémantique de sous-expressions de cette fonction présente le côté effets (modifications du tableau), mais la fonction elle-même n'a aucun effet secondaire externe, elle est donc pure.
Pour un exemple plus subtil, considérons une fonction qui écrit certaines données dans un fichier temporaire et se nettoie après elle-même. Dans une sémantique où il y a toujours assez de place pour que les fichiers temporaires et les programmes ne partagent pas les fichiers temporaires, la fonction n'a aucun effet secondaire; le fichier temporaire agit comme une mémoire supplémentaire utilisée par la fonction. Dans une sémantique qui prend en compte toutes les conditions du système de fichiers, la fonction a un effet secondaire - elle peut échouer en raison de circonstances externes. Dans une sémantique qui permet à la machine de planter, la fonction a un effet secondaire: s'il y a un crash pendant l'exécution de la fonction, le fichier temporaire peut être laissé. Dans une sémantique qui permet aux programmes exécutés simultanément de voir et peut-être de modifier le fichier temporaire, la fonction a un effet secondaire.