7
votes

Pourquoi la paresse va-t-elle bien avec la transparence référentielle?

Je lisais un didacticiel Haskell (en apprenant un haskell) dans lequel l'auteur a déclaré que la paresse se rend bien avec une transparence référentielle. Après plus de lecture et de recherche, je ne comprends toujours pas pourquoi. Notez que je comprends ce que je comprends ce qui est génial de transparence référentielle et de paresse, mais ce sont eux ensemble qui me trouble.

Y a-t-il un avantage particulier de la combinaison des deux?

Ou peut-être que l'auteur voulait juste dire qu'ils sont tous deux agréables à avoir et exprimé cette ambiguë?


1 commentaires

J'aurais choisi un libellé différent: prévenir des surprises désagréables, il est préférable que les expressions paresseuses soient transparentes de manière transparente. C'est plus une nécessité qu'une nettety.


3 Réponses :


5
votes

La transparence référentielle signifie que la fonction renvoie toujours la même sortie compte tenu de la même entrée. Donc, si cela n'a pas d'importance si la fonction est paresseuse ou stricte. La fonction paresseuse calculera sa production à un moment inconnu à l'avenir, mais en raison de la transparence référentielle, vous êtes garantis que la sortie sera toujours toujours pour les entrées données.

Donc, d'une manière, la transparence référentielle assure l'exactitude des fonctions paresseuses.


0 commentaires

11
votes

C'est vraiment facile. Une évaluation non stricte (par exemple laze) signifie que les tâches peuvent être reportées. Mais pour reporter quelque chose, vous êtes mieux sûr que vous obtiendrez plus tard le même résultat que vous obtiendriez maintenant, et c'est une transparence référentielle. Considérez cet impératif Code Java:

long start = System.currentTimeMillis(); //get the start time
runBenchmarkFunction();
System.out.println("Run took " + (System.currentTimeMillis() - start) + " ms"); 


3 commentaires

"L'état n'est nécessaire qu'à la troisième ligne". Ce n'est pas strictement vrai. L'effet secondaire d'avoir demandé au système de l'heure actuelle est nécessaire pour exécuter la deuxième ligne; Il est de type io a , pas a . RunBenchMarkFunction est de type similaire et pour exécuter les deux, vous devez les combiner avec une fonction qui garantit que des actions sont effectuées dans l'ordre, >> dans HASKELLL. Donc, vous écrivez vraiment actuelTime >> = \ \ st -> runbenchmparkfunction >> actuelTime >> = \ fin -> poststrln "il a pris" ++ (show $ end - st) ++ "secondes" . Il est clair que la deuxième ligne dépend du premier, de sorte que tout fonctionne.


@Jrockway: J'utilise ici une langue de fiction que vous pouvez appeler "Java paresseux" comme exemple très brut et facile d'expliquer la connexion entre la paresse et la transparence référentielle. Comment le problème est résolu dans HASKELL est une question complètement différente . Notez que "la voie de la monade" de Haskell n'est pas la seule possibilité, par exemple Nettoyer utilise son système de type pour faire face à ce problème.


La question est étiquetée "HASKELL". Mais toujours, ce que vous avez écrit est parfaitement transparent si vous imaginez la bonne sémantique. Et si vous imaginez une autre sémantique, alors ce n'est pas le cas. Mais le mot clé il y a "Imagine".



4
votes

Considérez ce code Python, où un générateur est utilisé pour calculer paresseusement une séquence infinie. Il n'a aucune transparence référentielle en raison de son utilisation de l'état mondial, d'où un appelant du générateur ne peut donc pas être sûr que le résultat qu'ils obtiennent n'a pas été affecté par un autre événement.

foo = 0

def foo_sequence():
    global foo
    while True:
        foo += 1
        yield foo

>>> generator = foo_sequence()
>>> generator.next()
1
>>> generator.next()
2
>>> foo = 5
>>> generator.next()
6


5 commentaires

Très bel exemple. Bien sûr, il est possible de casser une transparence référentielle à Haskell, bien qu'il y ait généralement des signes d'avertissement en cours de route.


@John: Vous voulez dire avec l'utilisation de trucs primitifs ou Unsafeperformio ? Ceux-ci sont considérés comme nocifs s'ils ne sont pas utilisés correctement. Ne peut pas imaginer une autre façon.


@Fuzxxl, c'est exactement ce que je veux dire, et le préfixe dangereux serait l'avertissement. Une autre manière consiste à envelopper un pointeur sur une bytretring, puis modifier le pointeur.


@John: Notez que nonafeperformio (et tout le reste avec dangereux dans son nom) ne fait pas partie de la norme Haskell, de sorte que vous ne pouvez pas réellement casser la transparence référentielle dans "Pure "Haskell (pas que c'est pratiquement pertinent).


@ SEPP2K, tandis que cela peut être vrai, il est toujours possible de faire des mauvaises choses à Haskell98. Voir Mail-Archive.com/hakell@hakell.org/msg21785.html . Si je comprends bien que le fil, bien que vous ne violez pas RT, vous violez la causalité. Ni satisfaire.