GHCiの基本的な使い方まとめ

Haskellコンパイラの`GHC`に付属する対話形式のコンパイラ、`GHCi`の基本的な使い方です。さらに詳しいドキュメントは、[Haskell.jp](https://ghcguide.haskell.jp/8.2.2/users_guide/ghci.html)[^1]、[公式ドキュメント](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html)を参照してください。この記事を書くにあたって使ったGHCのバージョンは`8.6.5`です。

## 起動

`GHCi`にパスが通っていれば、`ghci`とコマンドラインに叩くだけで起動できます。

```terminal
λ> ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
Prelude>
```

Haskellの式は、1行づつ実行できます。

```haskell
Prelude> putStrLn "Hello"
Hello
Prelude> let x = 3
Prelude> x ^ x
27
```

## GHCiの終了

`:quit`または`:q`で終了します。

```haskell
Prelude> :q
Leaving GHCi.
λ>
```

## 関数、型、型クラス名の補完

GHCiでは、関数などの名前をタブで補完してくれます。何も入力しないでタブを押すと、使用できる関数などを全て出力します。

```haskell
Display all 510 possibilities? (y or n)
!!                              Prelude.exp                     atan2
$                               Prelude.exponent                atanh
$!                              Prelude.fail                    break
...
```

```haskell
Prelude> a<tab>
abs         acosh       and         appendFile  asin        atan        atanh
acos        all         any         asTypeOf    asinh       atan2
```

## 複数行の入力

`:{`を入力して改行すると、複数行での入力が可能です。評価する際は`:}`で閉じられます。

```haskell
Prelude> :{
Prelude| add :: Int -> Int -> Int
Prelude| add x y = x + y
Prelude| :}
Prelude> add 4 18
22
```

## .hsファイルのロード

Haskellのソースコードは、`:load`(`:l`)でロードできます。

```haskell
-- ./main.hs
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n-1)

main = do
	putStrLn "Hello from a script!"
```

```haskell
Prelude> :load main.hs
[1 of 1] Compiling Main             ( main.hs, interpreted )
Ok, one module loaded.
*Main>
```

ファイルの中で定義した関数(型/型クラス/変数など)は、GHCi内で使用できます。

```haskell
*Main> fact 5
120
*Main> main
Hello from a script!
```

## 他ディレクトリへの移動

カレントディレクトリの下層ディレクトリにファイルがある場合は、`cd`で移動できます。

```haskell
Prelude> :cd dir
Prelude> 
```

## 外部モジュールのインポート

`import`文が使えますが、`:module`でもインポートできます。

```haskell
Prelude> import Data.List
Prelude Data.List> 
```

```haskell
Prelude> import Data.Map as Map
Prelude Map>
```

```haskell
Prelude> :m Data.List
Prelude Data.List>
```

```haskell
Prelude> :m +Data.Map
Prelude Data.Map>
```

## モジュール、ファイルのアンロード

`:m`でモジュール名の前に`+`をつけるとロードできますが、`-`でアンロードできます。

```haskell
Prelude Data.List> :m -Data.List
Prelude>
```

```haskell
*Main> :m -Main
Prelude>
```

## ファイルの再読み込み

元のファイルが変更されている場合は、`:reload`(`:r`)でリロードできます。

```haskell
*Main> :r
Ok, one module loaded.
*Main>
```

## 環境の確認

`:show`で、

- 束縛の一覧
- モジュールの一覧
- インポートの一覧

などを見られます。

```haskell
Prelude> :show bindings
x :: Num p => p = _
f :: p -> p = _
```

```haskell
Prelude Data.List> :show modules
Main             ( main.hs, interpreted )
Shapes           ( Shapes.hs, interpreted )
```

```haskell
Prelude Data.List> :show imports
import Data.List
import Prelude -- implicit
```

## 式や関数の型の確認

`:type`または`:t`で式の型(式が持つ値の型)や関数の型注釈を確認できます。

```haskell
Prelude> :t 3142
3142 :: Num p => p
Prelude> :t 'a'
'a' :: Char
Prelude> :t "aaa"
"aaa" :: [Char]
Prelude> :t Just 181
Just 181 :: Num a => Maybe a
Prelude> :t pred
pred :: Enum a => a -> a
```

ただし、`+`などの中置演算子は`()`で囲まないとエラーが発生します。

```haskell
Prelude> :t +

<interactive>:1:1: error: parse error on input ‘+’
Prelude> :t (+)
(+) :: Num a => a -> a -> a
```

## 型などについての情報の確認

`:info`(`:i`)で、その関数(型)が属する型クラス、型クラスであればインスタンス、そしてそれらが定義されているモジュールを確認できます。

```haskell
Prelude> :i map
map :: (a -> b) -> [a] -> [b]   -- Defined in ‘GHC.Base’
Prelude> :i Num
class Num a where
  (+) :: a -> a -> a
  (-) :: a -> a -> a
  (*) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInteger :: Integer -> a
  {-# MINIMAL (+), (*), abs, signum, fromInteger, (negate | (-)) #-}
        -- Defined in ‘GHC.Num’
instance Num Word -- Defined in ‘GHC.Num’
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Int -- Defined in ‘GHC.Num’
instance Num Float -- Defined in ‘GHC.Float’
instance Num Double -- Defined in ‘GHC.Float’
```

## カインドの確認

`:kind`(`:k`)で型コンストラクタや型、型クラスのカインド[^2]を確認できます。

```haskell
Prelude> :k Int
Int :: *
Prelude> :k Maybe
Maybe :: * -> *
Prelude> :k Functor
Functor :: (* -> *) -> Constraint
Prelude> :k Either
Either :: * -> * -> *
Prelude> :k []
[] :: * -> *
Prelude> :k ()
() :: *
```

## プラグマの設定

`:set <option>`でプラグマを設定できます。

```haskell
Prelude> f = (+2)
Prelude> f = (+3)
Prelude> :set -Wall -- {-# OPTIONS_GHC -Wall #-} と同義
Prelude> f = (+2)

<interactive>:4:1: warning: [-Wname-shadowing]
    This binding for ‘f’ shadows the existing binding
      defined at <interactive>:2:1
```

## その他のよく使うコマンド

| コマンド             | 処理                                         |
| -------------------- | -------------------------------------------- |
| `:`                  | 1つ前のコマンドを実行                        |
| `:?`(`:help`)        | 全てのコマンドを表示                         |
| `:doc <name>`        | モジュールなどのドキュメントを表示           |
| `:browse`            | モジュール内の関数を型注釈とともに一覧で表示 |
| `:edit`              | ロードしたファイルを編集                     |
| `:set editor <path>` | 編集する際のエディタをパスで設定             |

[^1]: ここで翻訳されているGHC Users GuideのGHCのバージョンは`8.2.2`です。[GitHub](https://github.com/haskell-jp/ghc_users_guide_ja)から翻訳に参加できます。

[^2]: カインドについては[こちらのページ](https://haskell.jp/blog/posts/2017/10-about-kind-system-part1.html)を参照してください。