2016-07-07 2 views
1

Je sais que cela fonctionne:HASKELL --- L'utilisation de "laisser" dans un "do" syntaxe dans GHCi

do name <- getLine; let nameTag = "Hello, my name is " ++ name in putStrLn nameTag 

Outre ce morceau de code lorsqu'il est chargé dans GHCi:

hey = do 
    name <- getLine 
    let nameTag = "Hello, my name is " ++ name 
    putStrLn nameTag 

mais cela ne fonctionne pas:

do name <- getLine; let nameTag = "Hello, my name is " ++ name; putStrLn nameTag 

donnant le message d'erreur suivant:

<interactive>:142:82: 
    parse error (possibly incorrect indentation or mismatched brackets) 

Pourquoi cela ne fonctionne-t-il pas? Puis-je le faire fonctionner? Si oui, alors comment?

+1

Veuillez formater votre code. –

+1

Le problème est que l'analyseur pense que la structure de votre code est 'let {nameTag = ...; putStrLn nameTag} 'où il attend une affectation au lieu de' putStrLn nameTag'. – Bakuriu

Répondre

5

Oui, vous pouvez utiliser des accolades autour de la liaison let (s) pour désambiguïser l'analyse syntaxique:

do name <- getLine; let { nameTag = "Hello, my name is " ++ name }; putStrLn nameTag 
+0

Merci! J'ai essayé d'utiliser des parenthèses, mais cela n'a pas fonctionné. Quelle est la différence fondamentale entre les accolades et les parenthèses dans Haskell? –

+1

@ RafałPłaszczyk Les crochets servent à délimiter les sous-expressions. Les accolades sont pour la syntaxe de langage ambigus. (Oh, et la syntaxe d'enregistrement ...) – MathematicalOrchid

+1

@ RafałPłaszczyk Vous avez probablement remarqué que Haskell est sensible à l'indentation. Fondamentalement, les parenthèses permettent d'écrire tout en une ligne, en écrivant des blocs ('do, let, where, case of ') au même niveau d'indentation que' {entry1; entry2; ...} '. Généralement pas nécessaire, sauf dans GHCi. Dans de nombreux cas, seuls ';' sont suffisants et les crochets peuvent être omis. – chi

4

Pour compléter la réponse par McKenna, l'erreur peut être expliqué comme suit: comparer ces deux lignes

do name <- getLine; let name1 = "One"; putStrLn name1 
do name <- getLine; let name1 = "One"; name2 = "Two"; putStrLn name1 

Un lecteur humain peut voir qu'ils signifient réellement

do { name <- getLine; let { name1 = "One" } ; putStrLn name1 } 
do { name <- getLine; let { name1 = "One"; name2 = "Two" }; putStrLn name1 } 

mais l'analyseur n'est pas C'est intelligent. Lorsque l'analyseur Haskell voit la partie de code commun

do name <- getLine; let name1 = "One"; 
            --^-- 

il doit décider si le dernier ; appartient au niveau do (comme dans le premier cas ci-dessus), ou au niveau let (deuxième cas). Il s'avère qu'il choisit let, et échoue plus tard.