Haskell (:) et (++) différences
Je suis désolé pour une question comme ça. Je ne suis pas trop sûr au sujet de la différence de la :
et ++
opérateur en Haskell.
x:y:[] = [x,y]
aussi
[x] ++ [y] = [x,y]
comme pour la fonction d'inversion qui se pose cette question, pour moi,
reverse ::[a]->[a]
reverse [] = []
reverse (x:xs) = reverse(xs)++[x]
Pourquoi ne pas les travaux suivants?
reversex ::[Int]->[Int]
reversex [] = []
reversex (x:xs) = reversex(xs):x:[]
donnant une erreur de type.
- Comme une note de côté, vous pouvez (et devriez) appel sans utiliser de parenthèses:
reverse (x:xs) = reverse xs ++ [x]
, ou vous allez trébucher lorsque vous travaillez avec des fonctions à plusieurs arguments. - Ne pas appeler des fonctions comme
func(arg)
. Pauvre Haskell. Toujours faire appel à des fonctions commefunc arg
. Code avec claire des espaces rend plus confiant et plus lisible le code. func arg
est en effet plus correct Haskell quefunc(arg)
mais je diraisf(x)
est plus lisible quef x
en général car elle correspond à la majorité des autres langues, et aussi la manière mathématique de la spécification d'une fonction. Donc, je dirais "plus confiant et plus lisible" est une question d'opinion.
InformationsquelleAutor DarthVader | 2009-11-30
Vous devez vous connecter pour publier un commentaire.
La
:
opérateur est connu comme le "contre" de l'opérateur et est utilisé pour ajouter un élément de tête de une liste. Donc[]
une liste etx:[]
est préfixantx
à la liste vide faire la liste[x]
. Ensuite, si vous le contrey:[x]
vous vous retrouvez avec la liste[y, x]
qui est le même quey:x:[]
.La
++
opérateur est la liste de l'opérateur de concaténation qui prend deux listes d'opérandes et "combiner" en une seule liste. Donc, si vous avez la liste[x]
et la liste[y]
vous pouvez concaténer comme ceci:[x]++[y]
pour obtenir[x, y
].Avis que
:
prend un élément et une liste de tout++
prend deux listes.Que de votre code qui ne fonctionne pas.
L'inverse de la fonction renvoie une liste. Depuis le
:
opérateur ne prend pas une liste comme premier argument et puisreverse(xs):x
est pas valide. Maisreverse(xs)++[x]
est valide.: conses un élément à une liste.
++ ajoute deux listes.
L'ancien a type
tandis que le second est de type
Concaténation (++)
Peut-être que je pense profondément dans cette mais,
comme je le comprends, si vous essayez de concaténer
les listes à l'aide de
(++)
par exemple:(++)
est de parcourir compléter la liste de gauche.En prenant un coup d'oeil à la code de l' (++) rend
d'autant plus clair.
Ainsi, il serait souhaitable d'éviter d'utiliser
(++)
, car à chaque appelreverse(xs)++[x]
la liste devient de plus (ou moins, selonsur le point de vue. De toute façon, le programme n'a qu'à traverser un autre
liste à chaque appel)
Exemple:
Permet de dire que je les mettre en œuvre inverse, comme proposé par concaténation.
L'inversion d'une liste [1, 2, 3, 4] devrait ressembler à quelque chose comme ceci:
Queue de la Récursivité à l'aide de l'opérateur cons (:)!!!
Une méthode pour traiter les piles d'appels est par l'ajout d'une accumulateur.
(il n'est pas toujours possible d'ajouter simplement un accumulateur. Mais la plupart de la
fonctions récursives on traite sont primitive récursive et peut donc
être transformé en queue de fonctions récursives.)
Avec l'aide de l'accumulateur, il est possible de faire de cet exemple
travail, à l'aide de l'opérateur cons
(:)
.L'accumulateur --
ys
dans mon exemple, il s'accumule le résultat courant et est transmis en tant que paramètre. En raison de l'accumulateur nous sommes maintenant en mesurepour utiliser le contre opérateur à accumuler le résultat en ajoutant le
à la tête de notre liste initiale à chaque fois.
Il y a une chose à noter ici.
L'accumulateur est un argument supplémentaire. Je ne sais pas si Haskell
fournit les paramètres par défaut, mais dans ce cas, il serait bien,
parce que vous serait toujours appeler cette fonction avec une liste vide
comme l'accumulateur comme suit:
reverse' [1, 2, 3, 4] []
Il y a beaucoup de littérature sur la queue de la récursivité et je suis
certes, il y a beaucoup de questions similaires sur
StackExchange /StackOverflow. Veuillez me corriger si vous trouvez des erreurs.
Salutations,
EDIT 1:
Sera Ness souligné quelques-uns des liens vers de bonnes réponses pour ceux d'entre vous qui sont intéressés:
EDIT 2:
Ok.
Grâce à dFeuer et de ses corrections, je crois que je comprends Haskell
un peu mieux.
1.Le
$!
est au-delà de ma compréhension. Dans tous mes tests, il semblefaire empirer les choses.
2.Comme dFeuer a souligné:
Le thunk représentant l'application de
(:)
àx
ety
est sémantiquement identique àx:y
mais prend plus de mémoire. Donc, c'est spécial pour l'opérateur cons(et paresseux constructeurs) et il n'est pas nécessaire de forcer les choses en aucune façon.
3.Si j'ai plutôt sumUp Entiers d'une liste à l'aide d'une très fonction similaire,
une évaluation rigoureuse par BangPatterns ou la
seq
fonctionva empêcher la pile de la croissance de la trop grande si elle est utilisée de manière appropriée. par exemple:
Avis le bang en face de y. Je l'ai essayé dans ghci et il
prend moins de mémoire.
(:)
àx
ety
est sémantiquement identique àx:y
mais prend plus de mémoire. Les constructeurs sont spéciales. Stricte les constructeurs ne sont pas si spécial.x
niy
doit être évaluée afin d'obtenirx:y
.foldl (+)
sans optimisation--vous obtenez un résultat qui est une grande chaîne de thunks vous avez besoin de force pour arriver à la somme. Avecreverse
, le pire que vous pourriez jamais obtenir serait thunk-cons-thunk-cons.... C'est un assez bon résultat sur son propre!f (g x y)
généralement, GHC permettra de créer un thunk représentantg x y
et de thunk pourf
. Mais sig
est un paresseux constructeur (c'est à dire, un constructeur dont la définition n'utilise pas!
), GHC s'appliquentg
directement, et de transmettre le résultat àf
. La sémantique est identique, mais il est plus rapide et permet d'économiser la mémoire.appname +RTS -s
).++
fonction, il est rare que vous verriez qu'avec d'autres langues, à mon avis, par exemple, je n'ai jamais pensé à regarder à l'intérieur de la définition deconcat
en JavaScript ou vu quelqu'un ou quelque JS livres jamais vous recommandons de vous renseigner à la sourcecons
a tendance à être un constructeur de type de l'exploitant. l'exemple ici est:
peut être utilisé dans delet..in..
expresion mais++
n'est passera de retour 1 mais
retournera une erreur
Variable not in scope x
Pour le rendre facile, pensez à
cons
comme cehttps://en.wikibooks.org/wiki/Haskell/Other_data_structures
En outre, si vous souhaitez inverser un tableau à l'aide des inconvénients. Voici un exemple, la connaissance est pris de Prolog