Pourquoi est-seq mauvais?
Haskell a une fonction magique nommé seq
, qui prend un argument de n'importe quel type et le réduit à la Faiblesse de la Tête à la Forme Normale de (WHNF).
J'ai lu un couple de sources [pas que je peux me rappeler qui ils étaient maintenant...] qui affirment que "polymorphe seq
est mauvais". En quoi sont-ils des "mauvais"?
De même, il est le rnf
fonction, ce qui réduit un argument pour Forme Normale (NF). Mais ce est une méthode de classe; il ne fonctionne pas pour les types arbitraires. Il semble "évident" pour moi, que l'on pourrait modifier le langage de spécification pour fournir ce qu'un primitif, semblable à seq
. Cela, sans doute, serait "encore plus mauvais" que d'avoir seq
. En quoi est-ce donc?
Enfin, quelqu'un a suggéré que le fait de donner seq
, rnf
, par
et similaires du même type que la id
fonction, plutôt que de la const
fonction comme il est maintenant, serait une amélioration. Comment donc?
- Le
seq
fonction n'est pas lambda définissable (j'.r., ne peut pas être défini dans le lambda-calcul), ce qui signifie que tous les résultats de lambda calcul ne peut plus faire confiance quand nous avonsseq
.
Vous devez vous connecter pour publier un commentaire.
Autant que je sache, un polymorphe
seq
fonction est mauvaise, parce qu'elle affaiblit gratuit théorèmes ou, en d'autres termes, certaines égalités qui sont valables sansseq
ne sont plus valides avecseq
. Par exemple, l'égalitévaut pour toutes les fonctions
g :: tau -> tau'
, toutes les listesxs :: [tau]
et toutes les fonctions polymorphesf :: [a] -> [a]
. Fondamentalement, cette égalité états quif
ne pouvez réorganiser les éléments de sa liste d'arguments ou de chute ou de dupliquer des éléments, mais ne peut pas inventer de nouveaux éléments.Pour être honnête, il peut inventer les éléments qu'il pourrait "insérer" un non-terminaison de calcul/erreur d'exécution dans les listes, comme le type de l'erreur est polymorphe. C'est, cette égalité déjà pauses dans un langage de programmation comme Haskell sans
seq
. La fonction suivante définitions de fournir un contre-exemple de l'équation. En gros, sur le côté gaucheg
"cache" l'erreur.Afin de résoudre l'équation,
g
doit être stricte, qui est, il a à la carte une erreur, une erreur. Dans ce cas, l'égalité tient à nouveau.Si vous ajoutez un polymorphe
seq
opérateur, l'équation pauses à nouveau, par exemple, à la suite de l'instanciation est un contre-exemple.Si l'on considère la liste
xs = [False, True]
, nous avonsmais, d'autre part
Qui est, vous pouvez utiliser
seq
pour rendre l'élément d'une certaine position de la liste dépendent de la definedness d'un autre élément dans la liste. L'égalité tient à nouveau sig
est total. Si vous êtes intereseted en libre théorèmes découvrez la gratuit théorème de générateur, qui vous permet de spécifier si vous envisagez une langue avec des erreurs ou même une langue avecseq
. Bien, cela semble être de moins en moins de pertinence pratique,seq
sauts de certaines transformations qui sont utilisés pour améliorer la performence des programmes fonctionnels, par exemple,foldr
/build
fusion échoue dans la présence deseq
. Si vous êtes intereseted dans plus de détails au sujet du libre-théorèmes en présence deseq
, prendre un coup d'oeil dans Gratuit Théorèmes en Présence de seq.Autant que je sache, il avait été connu qu'un polymorphe
seq
sauts de certaines transformations, lorsqu'il est ajouté à la langue. Cependant, la althernatives ont aussi des inconvénients. Si vous ajoutez un type de la classe de baseseq
, vous pourriez avoir à ajouter beaucoup de classe du type de contraintes à votre programme, si vous ajoutez unseq
quelque part, profondément vers le bas. En outre, il n'avait pas été un choix d'omettreseq
comme il l'avait déjà été connu qu'il y a des fuites qui peut être fixé à l'aide deseq
.Enfin, je pourrais manquer quelque chose, mais je ne vois pas comment un
seq
opérateur de typea -> a
serait de travailler. L'indice deseq
est qu'il évalue une expression à la tête de forme normale, si une autre expression est évaluée à la tête de forme normale. Siseq
a typea -> a
il n'y a pas de façon de faire de l'évaluation d'une expression dépend de l'évaluation d'une autre expression.map g (f xs) = f (map g xs)
Heu... Même dans un langage total avec pas deundefined
ouseq
qui ne tient pas.f = map (1 :)
g = (2 :)
xs = [[3], [4]]
implique rien de fantaisie, mais il ne fait absolument briser l'égalité. Ai-je raté quelque chose de vraiment évident ou est fondamentalement toute cette réponse profondément erronée?f
, qui ne pouvait pas inventer de nouveaux éléments, parce qu'il ne sait pas de quel type il fonctionne sur. Votref
a besoin d'au moins unNum
contrainte, il ne peut pas être[a] -> [a]
.Un autre contre-exemple est donné dans cette réponse - monades ne parviennent pas à satisfaire monade lois avec
seq
etundefined
. Et depuisundefined
ne peut pas être évité dans un Turing-complet de la langue, le seul à blâmer estseq
.