11
votes

Conseils sur l'apprentissage "Comment penser fonctionnel"?

En tant que débutant dans les langages fonctionnels (j'ai commencé à toucher Erlang, il y a quelques semaines - la première langue fonctionnelle que je pourrais obtenir mes mains).

J'ai commencé à écrire quelques petits algorithmes (tels que gaucher_rotate_list , bubble_sort, fusion_sort etc.). Je me suis retrouvé souvent à perdre des décisions telles que "Devrais-je utiliser une liste d'assistance pour le stockage de résultats intermédiaire?" et "devrais-je créer une fonction d'assistance pour faire cela?"

Après un certain temps, j'ai trouvé cette programmation fonctionnelle (supporter avec moi si ce que je parle n'a aucun sens du tout) encourage un design "haut en bas": c'est-à-dire quand je fais merge_sort, vous écrivez d'abord toute la fusion trier les étapes et les nommer en tant que fonctions individuelles d'assistance; Et ensuite, vous mettez en œuvre ces fonctions d'assistance un par un (et si vous avez besoin de diviser davantage ces fonctions d'assistance, faites-la dans la même approche).

Cela semble contredire un design OO un peu, dans lequel vous pouvez commencer à partir du bas pour construire la structure de données de base, puis assembler la structure de données et les algorithmes dans ce que vous voulez.

Merci pour des commentaires. Oui, je veux obtenir des conseils sur la façon de "penser dans la langue fonctionnelle" (tout comme "penser à Java", "penser à C ++").


2 commentaires

Vous voulez des suggestions pour «Guide de programmation fonctionnelle pour les programmeurs de l'OOP»?


Mahin, mettez à jour la question. Merci pour votre réponse.


5 Réponses :


4
votes

Après un certain temps, j'ai trouvé que la programmation fonctionnelle [...] encourage un design "haut en bas".

Je ne suis pas sûr que ce soit une déclaration précise. J'ai récemment essayé de m'apprendre à moi-même une programmation fonctionnelle et j'ai découvert qu'un style de programmation "ascendant up" aident vraiment à moi. Pour utiliser votre exemple de trier de fusion:

  • examine d'abord le cas de base. Comment triez-vous un tableau de 0/1 éléments?
  • Suivant, regardez la base + 1, base + 2, ... étuis. Finalement, vous devriez voir un motif (division en sous-émérillants, résoudre les sous-émérules, combinaison de sous-performances) qui vous permet d'écrire un cas récursif général plutôt que d'atteindre le boîtier de base.
  • La fractionnement en subproblèmes est facile, mais la combinaison des substructions est un peu plus difficile. Vous avez besoin d'un moyen de fusionner deux tableaux triés dans une matrice triée.
  • Maintenant maintenant tout mis ensemble. Félicitations, vous venez d'écrire un type de fusion. :)

    Je pourrais avoir une mauvaise utilisation du terme, mais cela ressemble à un design ascendant pour moi. La programmation fonctionnelle est différente de la programmation orientée objet, mais vous ne devriez pas avoir besoin d'abandonner totalement les techniques de conception existantes lorsqu'elle est commutée entre les deux.


0 commentaires

10
votes

Une réponse est que la programmation fonctionnelle consiste à programmer à l'aide de fonctions, car elles sont définies en mathématiques (en bref, des éléments sans effets secondaires qui plantent des valeurs du domaine à la codomaine). Traduire en réalité que la partie "Comment penser" est la partie agitant par la main qui est difficile à être exhaustive, mais j'étillonnerai certaines de mes pensées:

  1. La définition est plus importante que l'efficacité. C'est-à-dire une mise en œuvre évidemment correcte d'une fonction que l'on peut comprendre que tout le comportement est meilleur qu'un complexe optimisé celui qui est difficile à raisonner. (Et devrait être préféré aussi longtemps que possible; jusqu'à ce qu'il y ait des preuves, il faut briser cette belle propriété.)
  2. Une fonction mathématique n'a pas d'effets secondaires. Un programme utile doit avoir des effets secondaires. Un programmeur fonctionnel est conscient des effets secondaires, comme une chose très dangereuse et compliquée, et conçoit le programme comme bande de fonctions qui prennent des valeurs de sortie d'un effet secondaire et crée des valeurs d'entrée à l'effet secondaire suivant.

    Le numéro un est associé au vague: "Code élégant". La liste des compréhensions peut présenter des équations très succinctes et mathématiques telles que des définitions des fonctions. Il suffit de regarder la sorte quick-trace implémentée avec des LCS. C'est ainsi que je définis l'élégance, succinct et rend tous les comportements clairs. Pas que Perl code-golf où vous êtes le plus souvent terres et cryptique.

    numéro deux est quelque chose que j'utilise quotidiennement jour dans la programmation. Divisez le code en fonctions (méthodes, routines, etc.) de l'état actuel qui sont des calculs libres d'effet secondaire donnant des intrants à la prochaine action à prendre (même que la prochaine action à prendre est). Lorsque la valeur est renvoyée, donnez-la à une routine qui effectue l'action décrite, puis recommencez.

    Dans ma tête I Diagramme Un processus Erlang en tant que graphique de la machine à états, où chaque sommet est un effet secondaire et une fonction dont la sortie est le bord pour choisi le sommet du sommet. Le paradigme de programmation fonctionnelle m'a appris à considérer les effets secondaires. Surtout à Erlang, étant donné que les effets secondaires comptent vraiment en concurrence et Erlang rend la concurrence très disponible.

    De la même manière, certaines tribus isolées n'ont qu'un mot pour les nombres ci-dessus 3 ou aucun mot pour "mien" / "le vôtre". On sent que les langues populaires ne disposent pas de mots pour "cela entraînera un effet secondaire", mais la programmation fonctionnelle l'a fait. Il vous oblige à être conscient de tout le temps, et c'est une bonne chose.


0 commentaires

2
votes

Je me suis retrouvé souvent à perdre des décisions telles que "Devrais-je utiliser une liste d'assistance pour le stockage de résultats intermédiaire?" et "devrais-je créer une fonction d'assistance pour faire cela?"

Mes conseils pour cela: Lisez Le petit SCHEMER . Vous pouvez le suivre à Erlang. C'est un bon livre pour vous exercer une idée de cela.


0 commentaires

5
votes

Après un certain temps, j'ai trouvé que la programmation fonctionnelle [...] encourage un design "haut en bas".

Eh bien, il ne s'agit pas de "descendre" ou "bas up". Il s'agit de se concentrer sur le "quoi" du problème, plutôt que de "comment". Lorsque j'ai démarré avec une programmation fonctionnelle, j'ai constaté que j'avais continué à rappeler des constructions impératives comme le pour en boucle en C. Puis j'ai rapidement découvert que tenter de traduire ma pensée impérative aux constructions fonctionnelles était très difficile. Je vais essayer de vous donner un exemple plus concret. Je vais mettre en œuvre un programme équivalent dans C et Haskell et tenter de retracer mon processus de pensée dans les deux cas. Notez que j'ai été explicitement verbeuse dans le but d'explication.

en C: xxx

trace de mon processus de pensée: < ol>

  • pense aux étapes. Tout d'abord, acceptez un numéro de l'utilisateur. Laissez ce numéro être appelé InputNumber . scanf () écrit.
  • Algorithme de base: un nombre est prime, sauf preuve contraire. primeflag déclaré et défini égal à 1 .
  • vérifier primenumber contre chaque numéro de 2 à primenumber / 2 . pour boucle a commencé. Déclaré une variable de boucle i pour vérifier primenumber contre.
  • Pour réfuter notre assertion initiale selon laquelle le numéro est préféré, cochez primenumber contre chaque i . Au moment où nous trouvons même un i qui divise primenumber , définissez primeflag sur 0 et break . Corps de boucle écrit.
  • Après avoir traversé notre processus de vérification rigoureux dans la boucle pour , cochez la valeur de PrimeFlag et signalez-le à l'utilisateur. printf () écrit.

    in haskell: xxx

    trace de mon processus de pensée:

    1. Un nombre est prime s'il n'a pas de diviseur mais un et un seul. Donc, NULL DIGISORS .
    2. Comment construisons-nous diviseurs ? Tout d'abord, écrivons une liste de candidats possibles. Écrit Down Texas Gamme de 2 à Number / 2.
    3. Maintenant, filtrez la liste et choisissez uniquement des éléments qui sont vraiment des diviseurs du nombre. A écrit le filtre mod x y == 0

      Je veux obtenir des conseils sur la façon de "Pensez à la langue fonctionnelle"

      OK, avant tout, pensez "quoi", pas "comment". Cela peut prendre beaucoup de pratique pour s'habituer à. De plus, si vous étiez autrefois un programmeur C / C ++ comme moi, arrêtez de vous inquiéter de la mémoire! Les langues modernes ont un collecteur à ordures et il est écrit pour que vous puissiez utiliser, alors n'essayez même pas de modifier les variables en place. Une autre chose qui m'a personnellement aidé: Écrivez des définitions en forme d'anglais dans votre programme afin de résumer les fonctions qui font la levée lourde.


  • 2 commentaires

    Votre exemple fonctionnel n'est-il pas un élément de code impératif dans un déguisement fonctionnel? Cela ne voudrait-il pas que cela décrive votre intention plus? ASSERTPRIMIME X = X ELEM PRIMES X , PRIMES X = Sieve [1..x] , où le tamis est le générateur de prime naïf?


    Je ne comprends pas - comment va ma pièce impérative? Nos approches du problème sont différentes, mais mon code est pur non monadic Haskell. Pas de pas, et pas d'effets secondaires. Votre approche génère d'abord une liste de nombres premiers, puis vérifie si l'élément donné se trouve dans la liste. D'autre part, mon approche fonctionnelle est semblable à mon approche impérative - j'ai fait cela exprès de comparer et d'illustrer.



    0
    votes

    Il est importé pour vous habituer à penser que les données peuvent être utilisées comme code et vice versa .

    Habituellement, vous construisez un programme (données) à l'aide de plusieurs opérations primitives (pliage, nidification, filetage, distribution, ... et certains sont des produits internes généralisés, des produits extérieurs, etc.) et utilisez ce programme (données) à manipuler d'autres données.

    Après un certain temps, j'ai trouvé cela fonctionnel la programmation [...] encourage un "top Down "Conception.

    Je suis d'accord.


    0 commentaires