対話環境は便利ですが、Haskellでは強い静的型付け・純粋関数型という言語の性質から、
コンパイラと対話環境とでは少々使い勝手が違います。
ここでは、Haskell初心者がghciを使うときに陥りがちな4つの落とし穴について紹介します。
1. 式を定義しようとしたら parse error on input `='
[原因] ghciはインタプリタなので、与えられた式全体を評価しようとする
Prelude> hoge = "foo"
<interactive>:5:6: parse error on input `='
[解決方法] let構文を利用する
Prelude> let hoge = "foo"
Prelude> hoge
"foo"
2. 式を評価しようとしたら No instance for (Show Hoge)
- ghciはIOモナドの中にいて、式を与えるたびprint (式)を実行している
- 式を表示可能にするためには、型がShowクラスのインスタンスである必要がある
 (printは型Show a => a -> IO ()を持つ。)
[原因1] 自分で定義した代数的データ型がShowクラスに属していない
Prelude>  data Tree a = Branch (Tree a) (Tree a) | Leaf a
Prelude> Leaf "hoge"
<interactive>:5:1:
    No instance for (Show (main::Interactive.Tree [Char]))
      arising from a use of `print'
    Possible fix:
      add an instance declaration for
      (Show (main::Interactive.Tree [Char]))
    In a stmt of an interactive GHCi command: print it
[解決方法] deriving Showをつけて自動的にShowクラスのインスタンスになるようにする
Prelude> data Tree a = Branch (Tree a) (Tree a) | Leaf a deriving Show
Prelude> Leaf "hoge"
Leaf "hoge"
[原因2] 簡約結果の型が関数
Prelude> let addOne = (+1)
Prelude> addOne
<interactive>:15:1:
    No instance for (Show (Integer -> Integer))
      arising from a use of `print'
    Possible fix:
      add an instance declaration for (Show (Integer -> Integer))
    In a stmt of an interactive GHCi command: print it
[解決方法] 諦める or 関数適用した結果を表示するようにする
3. do式を書こうとして改行したら Empty 'do' block (または複数行に渡る式が書けない)
[原因] 一行ずつ実行される対話環境では、インデント記法ではdo式の終端を判断できない
-- parseAtom :: Parser LispVal
parseAtom = do
 first <- letter <|> symbol
 rest <- many (letter <|> digit <|> symbol)
 let atom = first:rest
 return $ case atom of 
  "#t" -> Bool True
  "#f" -> Bool False
  _ -> Atom atom
このような式をghciで定義しようとして、
一行目を入れて改行したところで、
Prelude> let parseAtom = do
<interactive>:12:17: Empty 'do' block
となる。
[解決方法1] brace記法を利用して頑張って一行に収める
braceで囲えば、;がデリミタとして使える。
let parseAtom = do { 
 first <- letter <|> symbol; rest <- many (letter <|> digit <|> symbol); let {atom = first:rest}; return $ case atom of { "#t" -> Bool True; "#f" -> Bool False; _ -> Atom atom } } :: Parser LispVal -- ここまで改行なし
このように頑張って一行に収めればdo構文をghciで利用できる。
case構文もbrace記法で記述できる。
ちなみに、brace記法の場合、do構文の中でlet構文を利用する場合、もう一段{ ~ }で囲ってやらなきゃいけない。
(http://stackoverflow.com/questions/15273158/how-do-i-use-a-let-within-a-do-block-in-ghci)
[解決方法2] ghciのmultilineコマンドを実行する
- 
:から始まる行はghciのコマンド
- 
:{と:}のセットとなったmultilineコマンドを利用することで、複数行に渡る式を記述できる
ghci> :{
ghci| let parseAtom = do
ghci|      first <- letter <|> symbol
ghci|      rest <- many (letter <|> digit <|> symbol)
ghci|      let atom = first:rest
ghci|      return $ case atom of 
ghci|       "#t" -> Bool True
ghci|       "#f" -> Bool False
ghci|       _ -> Atom atom
ghci| :}  :: Parser LispVal
この場合、一行目のparseAtomの先頭よりも二行目以降が右側にインデントされていないと、
インサイドルールにより構文エラーとなる。どこかからソースをコピペしようとする場合、先頭にlet を加えただけで実行しようとすると構文エラーになるので、二行目以降の各行を4文字分インデントする必要がある。
4. 式を評価しようとしたら Ambiguous type variable   in the constraint
[原因] あなたが評価しようとしている式には文脈が足らない
- HaskellのようなHM型の静的型付け言語は式に多相性があり、型推論を行うことで最終的な型が決定される
- ソースコードの一部を抜き出してインタプリタで実行するだけでは、型を推論するのに情報が足らない場合がある
[解決方法] 型注釈を与える
let hogehoge = fugafuga :: Hoge let構文の末尾に型注釈を書ける
multilineコマンドを利用しlet式で長い関数を定義用とする場合は、
Prelude> :{
Prelude | let parseString = do
Prelude |                     char '"'
Prelude |                     x <- many (noneOf "\"")
Prelude |                     char '"'
Prelude |                     return $ String x :: Parser LispVal
Prelude | :}
こんな感じ。式xのみを注釈しているように見えるが、ちゃんとletで定義した式全体の型を注釈している。