2016-10-17 4 views
1

Pourquoi l'interpréteur Haskell (GHCI 7.10.3) a besoin de définitions de fonction pour être dans une expression let, mais le compilateur Haskell (GHC 7.10.3) lève une erreur d'analyseur si un définition de fonction est dans une expression let?Compilé vs Interprété: Laisser ou ne pas laisser

Je travaille à travers "Learn You a Haskell for Great Good!" La première fonction de Baby est doubleMe: doubleMe x = x + x

Pourquoi l'interpréteur accepte-t-il cette définition s'il se trouve dans une expression let et sinon lance une erreur d'analyse sur l'entrée '='? En attendant, si je compile la même fonction à partir d'un fichier, pourquoi GHC lance-t-il une erreur d'analyse si la définition de la fonction est dans une expression let et compile la définition si elle n'est pas dans une expression let? Venant d'un contexte Lisp, je suis surpris que Haskell interactif et le chargement et la compilation de fichiers Haskell traite ces définitions différemment.

+2

C'est une convention. Si GHCi fonctionnait exactement comme dans un fichier .hs, écrire '1 + 1' serait une erreur, ainsi que' print (2,3) '. Au lieu de cela, GCHi a choisi d'utiliser un peu de magie pour accepter à la fois ces expressions et les définitions 'let'. A propos de pourquoi "x = 1" sans laisser est rejeté - Je ne pense pas qu'il y ait une réponse claire à cela, sauf "cela nécessiterait plus de magie". – chi

+0

Droite. FWIW, [IHaskell] (https://github.com/gibiansky/IHaskell) permet de mélanger les deux styles. – leftaroundabout

+7

La nouvelle version de GHCi (8.0.1) accepte 'doubleMe x = x + x'. Assez de gens comme vous se sont plaints qu'ils ont ajouté un cas spécial pour cela. :) – Alec

Répondre

0

Les implémentations Modern Lisp sont compilées en code natif, souvent par défaut même lorsque le code est entré à l'invite. L'invite de Lisp n'est pas seulement un endroit pour entrer des commandes, c'est un endroit pour interagir avec la langue parce que la langue entière est rendue disponible par la boucle Read-Evaluate-Print.Cela signifie que Lisp lit le texte dans des expressions symboliques, qu'il évalue ensuite, en imprimant toutes les sorties d'impression et toutes les valeurs renvoyées. Par exemple,

? (defun a-fun() nil) 
A-FUN 
? (compiled-function-p #'a-fun) 
T 

Compiled-Function-P Clozure Common Lisp

Avec Lisp, le code, vous pouvez entrer dans l'image Lisp en compilant et en chargeant un fichier que vous pouvez également entrer dans l'image Lisp en le tapant sur le REPL. Il s'est avéré que j'étais surpris parce que je m'attendais à ce que l'invite GHCi soit une REPL, mais comme le décrit @Alec, ce n'est pas parce qu'il ne lit pas le texte dans les expressions Haskell qu'il évaluerait, comme le fait Lisp. Comme le dit @dfeuer, le problème n'est pas la compilation contre l'interprétation. Le problème est que l'invite de GHCi offre une interaction limitée avec un compilateur Haskell, plutôt qu'une interaction avec Haskell lui-même comme REPL de Lisp.

4

Le raisonnement derrière cela est que GHCi (en 7.10.3) attend à l'invite seulement

  • commands (type dans :h à la liste des commandes disponibles)
  • declarations (des choses comme data, type, newtype, class, instance, deriving et foreign mais pas une définition régulière)
  • imports
  • expressions (des choses comme 1+1 ou let x = 3 in x*x)
  • I/O Actions/do statments (des choses comme print "hi" ou x <- getLineOUlet doubleMe x = x + x)

Si cela semble surprenant de vous, rappelez-vous que l'évaluation de Lisp et Haskell est très différent - Lisp vient d'être interprété, tandis que Haskell est en cours de compilation. Comme vous pouvez le constater, les définitions de niveau supérieur ne font pas partie de cette liste. Heureusement, cela a été corrigé dans GHCi 8.0.1, qui prend désormais en charge les déclarations de fonctions de niveau supérieur. Les ouvrages suivants (en 8.0.1):

ghci> doubleMe x = x + x 
ghci> doubleMe 1 
2 
+4

Cela n'a rien à voir avec la compilation et l'interprétation. Beaucoup de Lisp est en fait compilé, je crois, bien que je pense que Scheme soit le seul Lisp qui soit vraiment conçu pour une bonne compilation. – dfeuer

+1

Je soupçonne que la motivation réelle pour ne pas inclure cette fonctionnalité dans les premières versions de ghci est le comportement surprenant de par ex. 'maybeDoubleMe Nothing = Rien \ nmaybeDoubleMe (Just x) = Juste (x + x)' dans ghci comparé à dans un fichier. –

3

La ligne de commande de l'interpréteur GHCi traite son entrée comme si elle était dans une clause do. Ainsi, vous pouvez taper ceci:

:module + System.Random 
v <- getStdRandom $ randomR (1,10) 

En dehors de la directive :module c'est exactement comment il serait dans une clause do.

De même, vous pouvez écrire

let f x = 2 * x 

parce que c'est la façon dont il serait dans une clause do.