Analyseur applicatif bloqué dans une boucle infinie

Shou Ya

J'essaye d'implémenter mon propre analyseur applicatif, voici le code que j'utilise:

{-# LANGUAGE ApplicativeDo, LambdaCase #-}

module Parser where

-- Implementation of an Applicative Parser

import Data.Char
import Control.Applicative (some, many, empty, (<*>), (<$>), (<|>), Alternative)

data Parser a = Parser { runParser :: String -> [(a, String)] }

instance Functor Parser where
  -- fmap :: (a -> b) -> (Parser a -> Parser b)
  fmap f (Parser p) = Parser (\s -> [(f a, s') | (a,s') <- p s])

instance Applicative Parser where
  -- pure :: a -> Parser a
  -- <*> :: Parser (a -> b) -> Parser a -> Parser b
  pure x = Parser $ \s -> [(x, s)]
  (Parser pf) <*> (Parser p) = Parser $ \s -> 
               [(f a, s'') | (f, s') <- pf s, (a, s'') <- p s']

instance Alternative Parser where
  -- empty :: Parser a
  -- <|> :: Parser a -> Parser a -> Parser a
  empty = Parser $ \_s -> []
  (Parser p1) <|> (Parser p2) = Parser $ \s ->
      case p1 s of [] -> p2 s
                   xs -> xs

char :: Char -> Parser Char
char c = Parser $ \case (c':cs) | c == c' -> [(c,cs)] ; _ -> []

main = print $ runParser (some $ char 'A') "AAA"

Quand je l'exécute, il reste bloqué et ne revient jamais. Après avoir creusé le problème, j'ai identifié la cause première de ma mise en œuvre de la <|>méthode. Si j'utilise l'implémentation suivante, tout se passe comme prévu:

instance Alternative Parser where
  empty = Parser $ \_s -> []
  p1 <|> p2 = Parser $ \s ->
    case runParser p1 s of [] -> runParser p2 s
                           xs -> xs

Ces deux implémentations sont, à mon avis, assez équivalentes. Ce que je suppose, c'est que cela peut avoir quelque chose à voir avec le système d'évaluation paresseux de Haskell. Quelqu'un peut-il expliquer ce qui se passe?

Daniel Wagner

Fait "star": dans votre mise en œuvre de (<*>):

Parser p1 <*> Parser p2 = ...

... nous devons calculer suffisamment pour savoir que les deux arguments sont en fait des applications du Parserconstructeur à quelque chose avant de pouvoir passer au côté droit de l'équation.

Fait "pipe strict": dans cette implémentation:

Parser p1 <|> Parser p2 = ...

... nous devons calculer suffisamment pour savoir que les deux analyseurs sont en fait des applications du Parserconstructeur à quelque chose avant de pouvoir passer au côté droit du signe égal.

Fait "pipe paresseux": dans cette implémentation:

p1 <|> p2 = Parser $ ...

... nous pouvons passer à la partie droite du signe égal sans faire de calcul sur p1ou p2.

Ceci est important, car:

some v = some_v where
    some_v = pure (:) <*> v <*> (some_v <|> pure [])

Prenons votre première implémentation, celle dont nous connaissons le fait "pipe strict". Nous voulons savoir si some_vc'est une application de Parserquelque chose. Merci à fait « star », il faut donc savoir si pure (:), vet some_v <|> pure []sont des applications de Parserquelque chose. Pour connaître ce dernier, en fait "pipe strict", il faut savoir si some_vet pure []sont des applications de Parserquelque chose. Oups! Nous venons de montrer que pour savoir s'il some_vs'agit d'une application de Parserà quelque chose, nous devons savoir si some_vest une application de Parserà quelque chose - une boucle infinie!

D'un autre côté, avec votre deuxième implémentation, pour vérifier si some_vc'est a Parser _, nous devons toujours vérifier pure (:), vet some_v <|> pure [], mais grâce au fait "pipe paresseux", c'est tout ce que nous devons vérifier - nous pouvons être sûrs que some_v <|> pure []c'est un Parser _sans premier vérifier récursivement que some_vet pure []sont.

(Et ensuite, vous en apprendrez davantage sur newtype- et serez encore une fois confus lorsque le passage de dataà newtypefait que les deux implémentations fonctionnent!)

Cet article est collecté sur Internet, veuillez indiquer la source lors de la réimpression.

En cas d'infraction, veuillez [email protected] Supprimer.

modifier le
0

laisse moi dire quelques mots

0commentaires
connexionAprès avoir participé à la revue

Articles connexes

Topshelf start bloqué dans une boucle infinie

onDataChange bloqué dans une boucle infinie

Script Python bloqué dans une boucle infinie

Authentification IIS-Windows bloquée dans une boucle infinie

L'effet est bloqué dans une boucle infinie - Ngrx / effets

La classe "let" est bloquée dans une boucle infinie

Le programme de loterie est bloqué dans une boucle infinie

L'instruction Do-While est bloquée dans une boucle infinie

javax.ws.rs.core.Response.readEntity () bloqué dans une boucle infinie

LinkedList sans champ de queue reste bloqué dans une boucle infinie

la macro semble bloquée dans une boucle infinie, je ne sais pas comment déboguer

Pourquoi mon programme Java est-il bloqué dans une boucle while infinie pour certaines valeurs?

Pourquoi cette fonction ne reste-t-elle pas bloquée dans une boucle infinie ?

Être bloqué en exécutant une boucle javascript infinie dans Selenium Chromedriver de Python

jeu de dés de craps bloqué dans une boucle infinie

C - pcap_findalldevs pour afficher toutes les interfaces est bloqué dans une boucle infinie

Ma fonction menu.displayHomeMenu(m) est bloquée dans une boucle infinie. Pourquoi?

Pourquoi mon code est-il bloqué dans une boucle infinie lors du scraping ?

Recherche binaire bloquée dans un python en boucle infinie

Comment éviter que PyQt Line Edit et Message Box ne soient bloqués dans une boucle infinie?

Switch Statement bloqué dans une boucle infinie lors de l'utilisation du cas par défaut c++

htaccess redirect bloqué dans une récursion infinie

Traverse JavaFileObjects entre dans une boucle infinie

Comment éviter une boucle infinie dans BFS?

React onChange coincé dans une boucle infinie

Coincé dans une boucle pas si infinie?

Comment interrompre une boucle infinie dans Prolog

Meta refresh entre dans une boucle infinie

Fonction Sleep() dans une boucle while infinie

TOP liste

  1. 1

    comment afficher un bouton au-dessus d'un autre élément ?

  2. 2

    impossible d'obtenir l'image d'arrière-plan en plein écran dans reactjs

  3. 3

    Je continue à obtenir l'objet 'WSGIRequest' n'a pas d'attribut 'Get' sur django

  4. 4

    comment supprimer "compte de connexion google" à des fins de développement - actions sur google

  5. 5

    Conversion double en BigDecimal en Java

  6. 6

    Impossible d'accéder à la vue personnalisée pendant le test de l'interface utilisateur dans XCode

  7. 7

    Algorithme: diviser de manière optimale une chaîne en 3 sous-chaînes

  8. 8

    Passer la taille d'un tableau 2D à une fonction ?

  9. 9

    Comment obtenir l'intégration contextuelle d'une phrase dans une phrase à l'aide de BERT ?

  10. 10

    Comment changer le navigateur par défaut en Microsoft Edge pour Jupyter Notebook sous Windows 10 ?

  11. 11

    CSS: before ne fonctionne pas sur certains éléments,: after fonctionne très bien

  12. 12

    Comment créer un bot à compte à rebours dans Discord en utilisant Python

  13. 13

    Comment ajouter une entrée à une table de base de données pour une combinaison de deux tables

  14. 14

    Exporter la table de l'arborescence vers CSV avec mise en forme

  15. 15

    Comment activer le message Pylint "too-many-locals" dans VS Code?

  16. 16

    Créer un système Buzzer à l'aide de python

  17. 17

    Spring @RequestParam DateTime format comme ISO 8601 Date Heure facultative

  18. 18

    Empêcher l'allocation de mémoire dans la génération de combinaison récursive

  19. 19

    Déplacement des moindres carrés d'ajustement pour les déplacements de points ayant des problèmes

  20. 20

    Comment choisir le nombre de fragments et de répliques Elasticsearch

  21. 21

    Microsoft.WebApplication.targets

chaudétiquette

Archive