web-dev-qa-db-fra.com

Pourquoi mon code Haskell dit-il "variable pas dans la portée: main"?

Lorsque je tape ce qui suit dans le shell interactif de Haskell sur le site Web repl.it , cela fonctionne parfaitement.

let squareMe x = x * x
let myFruit = ["banana", "Apple", "kiwi", "orange"]

Mais quand je le tape dans un fichier source et que je clique sur 'Exécuter', le message d'erreur suivant s'affiche:

<interactive>:3:1: error:
    • Variable not in scope: main
    • Perhaps you meant ‘min’ (imported from Prelude)

J'essaie de comprendre cette erreur et de trouver une solution depuis quelques heures maintenant et je ne suis pas plus près de trouver une solution ou de comprendre ce que l'erreur signifie.

8
branty1970

Les programmes Haskell REPL (GHCi) et réels de Haskell sont très différents.

Les raisons de cette différence sont l’objectif des deux formats. Tout d'abord, GHCi est une zone de test, pas une zone d'exécution de code. Cependant, les fichiers source Haskell sont destinés à exécuter un certain processus, nommé main. Lorsque vous exécutez un fichier source, le compilateur Haskell (généralement GHC) recherche l'action IO appelée main et tente de l'exécuter. Dans ce cas, il n'y avait pas de main, donc cela a échoué.

Deuxièmement, ce que vous avez tapé n’est pas un programme Haskell valide, c’est une déclaration qui conviendrait dans GHCi, mais pas dans le code source Haskell. Ce serait correct dans un fichier source:

squareMe x = x * x

myFruit = ["banana", "Apple", "kiwi", "orange"]

Notez le manque de let; Les fichiers source Haskell ne l'utilisent pas pour déclarer des choses.

Notez que sur repl.it, il sera toujours déploré que main soit manquant, mais vous pouvez ensuite vous référer à squareMe et myFruit dans le REPL sans souci. En d'autres termes, l'erreur apparaîtra toujours, mais peu importe, car vous pouvez utiliser tout ce que vous avez écrit dans le fichier.

Si vous souhaitez supprimer l'avertissement, vous pouvez écrire les lignes suivantes:

main :: IO ()    -- This says that main is an IO action.
main = return () -- This tells main to do nothing.

Le programme pourrait faire beaucoup de choses à la place de cela. Voici quelques exemples:

  • main = putStrLn "No errors!" Imprimera No errors! lorsque vous l'exécuterez.
  • main = print myFruit Imprimera ["banana", "Apple", "kiwi", "orange"] lorsque vous l'exécuterez.

Veuillez noter que cette réponse s’applique principalement au site repl.it en particulier, bien qu’en général, c’est la façon dont les programmes Haskell sont structurés.

11
AJFarmar

Si vous compilez une source Haskell, il doit y avoir un symbole main comme point d'entrée, comme lors de la compilation, par exemple un programme en C. Également dans un fichier compilé, vous devez ignorer la lets. Par exemple.

squareMe x = x * x

main = do
    putStrLn (show (squareMe 4))
4
mschmidt

Si ce que vous écrivez ressemble plus à une bibliothèque ou à un ensemble de routines d’utilitaires qu’à un programme complet, vous pouvez le déclarer comme module. Ensuite, GHC le compilera en un objet que vous pourrez lier à d’autres programmes, et vous pourrez également le charger dans GHCI. On ne s'attendra pas à ce qu'il contienne une routine main.

Si vous enregistrez ceci dans un fichier .hs:

module Example (squareMe) where

squareMe x = x * x -- Exported to other modules.
myFruit = ["banana", "Apple", "kiwi", "orange"] -- Not exported.

Compiler ceci avec GHC vous donnera un fichier .hi et un fichier .o, et son exécution dans GHCI vous donnera ceci:

GHCi, version 8.0.2: http://www.haskell.org/ghc/  :? for help
Ok, modules loaded: Example (sx-modulexmpl.o).
Prelude Example> squareMe 2
4

Vous pouvez également calculer une expression qui référence une bibliothèque à partir de la ligne de commande. ghc -e "squareMe 2" Example.hs imprime 4.

0
Davislor