2017-10-03 17 views
3

repl.itウェブサイトのHaskellのインタラクティブシェルで次のように入力すると、完全に動作します。なぜ私のHaskellコードは「変数がスコープではない:main」と言っていますか?

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

しかし、私はソースファイルにそれを入力し、「ファイル名を指定して実行」をクリックしたときに、私はエラーを取得する:私はこのエラーを理解し、ための解決策を考え出すしようとしてきた

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

2時間以上かかることがあります。解決策を見つけることやエラーの意味を理解することに近づくことはありません。

+2

プログラムにはエントリポイントが必要です:プログラムは 'main'と呼ばれるモナド関数です。 –

+1

あなたが書いたものは本当に正しいものではありません。コードは完全ではありません(私は 'main'がありません)。また、[*なるように*]をチェックしてください(http://learnyouahaskell.com/syntax-in-functions#let-it-be)。最初からその本を読むことをお勧めします。 – KarelG

答えて

1

Haskellソースをコンパイルする場合、コンパイル時と同様に、エントリポイントとしてmainシンボルが必要です。 Cプログラム。また、コンパイルされたファイルでは、letをスキップする必要があります。例えば。

squareMe x = x * x 

main = do 
    putStrLn (show (squareMe 4)) 
+1

'print'の中で' show'を使う必要はありません。これはすでに入力タイプでは多相的です。 – leftaroundabout

+2

'print x = putStrLn(show x)'なので、あなたのコードは 'show'を2回呼び出します。 – melpomene

+0

@リア方向については、実際に。 'print'はおそらくプレリュードにあってはいけません。なぜなら、複数の値からの出力をまとめたり、改行を追加したりするのと同じように間違った関数になるからです。 'print = putStrLn。 showLay = readIO = "getLine"であり、これらの便利関数のどちらも教訓のオーバーヘッドに見合うものではない。 – dfeuer

5

Haskell REPL(GHCi)と実際のHaskellプログラムは大きく異なります。

この違いの理由は、2つの形式の目的です。第一に、GHCiはテスト領域であり、コード実行領域ではありません。しかし、Haskellのソースファイルは特定のプロセスを実行するためのもので、その名前はmainです。ソースファイルを実行すると、Haskellコンパイラ(通常はGHC)がというIOアクションを探して実行しようとします。この場合、mainが存在しないため、失敗しました。

第2に、あなたが入力したものは有効なHaskellプログラムではなく、GHCiではうまくいくがHaskellソースではない宣言です。これは、ソース・ファイルに正しい次のようになります。

squareMe x = x * x 

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

letの欠如に注意してください。 Haskellのソースファイルは、宣言にそれを使用しません。

repl.itでは、これはまだmainが不足していると言いますが、REPLのsquareMemyFruitを心配することなく参照できます。つまり、エラーは引き続き表示されますが、それでも問題はありません。なぜなら、ファイルに書いたものを使用できるからです。

警告を抑止したい場合は、行書くことができます:

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

を使用すると、プログラムがこれの代わりに行うかもしれない多くのものがあります。いくつか例があります:

  • main = putStrLn "No errors!"実行時にNo errors!が印刷されます。
  • main = print myFruit実行すると、["banana", "apple", "kiwi", "orange"]が印刷されます。

この回答は、特にreplsitサイトに適用されることに注意してください。一般的に、これはHaskellプログラムの構造です。

0

あなたが書いているのは、完全なプログラムよりもライブラリやユーティリティルーチンのようなものであれば、moduleと宣言できます。そして、GHCはそれを他のプログラムにリンクできるオブジェクトにコンパイルし、GHCIでロードすることもできます。 mainルーチンを含めることは予期されません。

あなたは.hsファイルにこれを保存する場合:

GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help 
Ok, modules loaded: Example (sx-modulexmpl.o). 
Prelude Example> squareMe 2 
4 
:あなた .hiファイルと .oファイルを与えるGHCでこれをコンパイルし、GHCiの中でそれを実行すると、あなたにこれを与える

module Example (squareMe) where 

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

コマンドラインからライブラリを参照する式を計算することもできます。 ghc -e "squareMe 2" Example.hsプリント4