Haskell入門

【Haskell】GHCiの主要なコマンド

【Haskell】GHCiの主要なコマンド

HaskellコンパイラであるGHC (Glasgow Haskell Compiler)のインタラクティブ対話型シェルのGHCiの主要なコマンドについて紹介します。

GHCi

Haskellのコンパイラで広く利用されているものはGHC (Glasgow Haskell Compiler)です。GHCには、インタラクティブな対話型シェルであるGHCiがあります。

GHCiを使うことでモジュール分割されたファイルの関数を個別に動作確認するといったことも可能となるため非常に便利です。Haskellでは、GHCiで各モジュールの関数を動作確認し、確認が終わったらGHCでコンパイルするという開発の流れが一般的です。

GHCiには様々なコマンドがありますが、主要なコマンドを把握しておくことは非常に役立ちます。本記事では、GHCiの主要なコマンドを紹介します。

GHCiの主要なコマンド

以降では、GHCiにおける主要なコマンドを紹介していきます。実行例で表示している「$」「ghci>」の部分については端末への入力を意味します。

GHCiを終了する (:q)

対話型インターフェースを使う場合にまず覚えないといけないことは、GHCiの終了方法です。GHCiを終了するには「:q」コマンドを使用します。

$ ghci
ghci> :q
Leaving GHCi.

ヘルプを表示する (:? または :help)

GHCiで使用できコマンドを表示する場合には「:?」または「:help」コマンドを使用します。

$ ghci
ghci> :?
 Commands available from the prompt:

   <statement>                 evaluate/run <statement>
   :                           repeat last command
   :{\n ..lines.. \n:}\n       multiline command
   :add [*]<module> ...        add module(s) to the current target set
   :browse[!] [[*]<mod>]       display the names defined by module <mod>
                               (!: more details; *: all top-level names)
   :cd <dir>                   change directory to <dir>
(...省略...)

ファイルをロードする(:l または :load

以下のようなtest.hsというプログラムがあるとします。このファイルをGHCiで読み込んで関数を実行する場合を例にファイルをロードする方法を説明します。

-- Test用Haskellプログラム
-- main関数を開始
main :: IO ()
main = do
    -- テスト出力
    print "Hello World!"

GHCiでHaskellプログラムを読み込む場合には、以下のように読み込むことができます。読み込んだ後でmain関数などのプログラム中の関数を呼び出して実行することが可能です。

$ ghci test.hs
[1 of 2] Compiling Main             ( test.hs, interpreted )
Ok, one module loaded.
ghci> main
"Hello World!"

GHCiを立ち上げた状態でHaskellプログラムを読み込む場合には「:l」または「:load」コマンドを使用します。

$ ghci
ghci> :l test.hs
[1 of 2] Compiling Main             ( test.hs, interpreted )
Ok, one module loaded.
ghci> main
"Hello World!"

型を表示する (:t または :type)

Haskellでは、強力な型システムが特徴的な関数型プログラミング言語です。そのため、型の情報を調べて正確に把握することは非常に重要になります。GHCiで、型を調べる際には「:t」または「:type」コマンドを使用します。

式の型を表示する

Haskellでは、単一の値、例えば数値や文字列、またはより複雑な関数の呼び出しなど、評価されるあらゆるものを式(expression)と呼びます。以下のように、Haskellでの式の型を確認することができます。

$ ghci
ghci> :t 10
10 :: Num a => a

上記では、数値10Num型クラスの任意のインスタンスaであることを示しています。これは、10が整数(Int)や倍精度浮動小数点数(Double)等のその他 Num型クラスのインスタンスである任意の数値型であることを意味します。

この型シグネチャは、10が特定の型に限定されていないことを示していて、Haskellの型推論システムがその文脈に応じて適切な具体的な型を選択できるようにします。

関数の型を表示する

関数の型を表示する場合には、以下のように確認することができます。以下は、reverse関数の型を確認してみた例です。

$ ghci
ghci> :t reverse
reverse :: [a] -> [a]

reverse :: [a] -> [a]は、Haskellの型シグネチャで、reverse関数が任意の型aのリスト([a])を受け取り、同じ型の要素を持つ新しいリストを返すことを意味しています。

この型シグネチャは、reverse関数が型に依存しない汎用関数であることを示しており、任意の型のリストに適用できることを意味しています。

型がどの型クラスのインスタンスかを表示する (:instances)

Haskellでは、型クラスのインスタンスとなっている型があります。型がどの型クラスのインスタンスとなっているかを確認したい場合には、「:instances」コマンドを使用します。

$ ghci
ghci> :instances Int
instance Bounded Int -- Defined in ‘GHC.Enum’
instance Read Int -- Defined in ‘GHC.Read’
instance Enum Int -- Defined in ‘GHC.Enum’
instance Integral Int -- Defined in ‘GHC.Real’
instance Num Int -- Defined in ‘GHC.Num’
instance Real Int -- Defined in ‘GHC.Real’
instance Show Int -- Defined in ‘GHC.Show’
instance Eq Int -- Defined in ‘GHC.Classes’
instance Ord Int -- Defined in ‘GHC.Classes’

上記例では、Int型は、BoundedReadEnumIntegralNumRealShowEqOrdといった型クラスのインスタンスとなっていることを示しています。

このようにどの型クラスのインスタンスかを確認することで、その型が有する特徴を把握することができるようになります。

情報を表示する (:info)

指定した識別子(変数、関数、型、型クラス等)に関する詳細情報を確認したい場合には、「:info」コマンドを使用します。以下では、いくつかの例を用いて紹介します。

以下結果を見てもらうと分かりますが:infoコマンドは、:type:instancesを包含したような情報を提供してくれます。

変数の情報

変数の情報は、以下のように確認できます。

$ ghci
ghci> let x = 10
ghci> :info x
x :: Num a => a         -- Defined at <interactive>:1:5

上記例では、GHCi上で定義したxについて情報を表示しています。xは、Num型クラスの任意のインスタンスaであることを示しています。また、定義されている場所に関する情報も付与されています。

関数の情報

関数の情報は、以下のように確認できます。以下は、reverse関数の情報を確認してみた例です。

$ ghci
ghci> :info reverse
reverse :: [a] -> [a] 	-- Defined in ‘GHC.List’

結果としては、:typeコマンドでの結果と似ていますが、リストの定義情報が提示されているなど追加の情報が表示されています。:typeコマンドが型の情報を表示するのに対して、:infoコマンドはより詳細な情報を表示します。

型の情報

型の情報は、以下のように確認できます。以下は、Maybe型の情報を確認してみた例です。

$ ghci
ghci> :info Maybe
type Maybe :: * -> *
data Maybe a = Nothing | Just a
  	-- Defined in ‘GHC.Maybe’
instance Semigroup a => Monoid (Maybe a) -- Defined in ‘GHC.Base’
instance Semigroup a => Semigroup (Maybe a)
  -- Defined in ‘GHC.Base’
instance Foldable Maybe -- Defined in ‘Data.Foldable’
instance Traversable Maybe -- Defined in ‘Data.Traversable’
instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
instance Applicative Maybe -- Defined in ‘GHC.Base’
instance Functor Maybe -- Defined in ‘GHC.Base’
instance MonadFail Maybe -- Defined in ‘Control.Monad.Fail’
instance Monad Maybe -- Defined in ‘GHC.Base’
instance Eq a => Eq (Maybe a) -- Defined in ‘GHC.Maybe’
instance Ord a => Ord (Maybe a) -- Defined in ‘GHC.Maybe’

上記では、Maybeの定義情報や、Maybeがどの型クラスのインスタンスかの情報を提供してくれます。

型クラスの情報

型クラスの情報は、以下のように確認できます。以下は、Monad型クラスの情報を確認してみた例です。

$ ghci
ghci> :info Monad
type Monad :: (* -> *) -> Constraint
class Applicative m => Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  (>>) :: m a -> m b -> m b
  return :: a -> m a
  {-# MINIMAL (>>=) #-}
  	-- Defined in ‘GHC.Base’
instance Monoid a => Monad ((,) a) -- Defined in ‘GHC.Base’
instance (Monoid a, Monoid b) => Monad ((,,) a b)
  -- Defined in ‘GHC.Base’
instance (Monoid a, Monoid b, Monoid c) => Monad ((,,,) a b c)
  -- Defined in ‘GHC.Base’
instance Monad ((->) r) -- Defined in ‘GHC.Base’
instance Monad IO -- Defined in ‘GHC.Base’
instance Monad Maybe -- Defined in ‘GHC.Base’
instance Monad Solo -- Defined in ‘GHC.Base’
instance Monad [] -- Defined in ‘GHC.Base’
instance Monad (Either e) -- Defined in ‘Data.Either’

上記では、Monadのクラス定義情報や、Monadがどの型クラスのインスタンスかの情報を提供してくれます。

型コンストラクタのカインドを表示する (:kind)

Haskellにおいて型コンストラクタとは、型を生成するためのもので他の型を引数として取ることができます。カインドとは、型コンストラクタが取ることのできる型引数を表すもので、型の「型」のようなものです。

GHCiの「:kind」コマンドを使用することで調べることができます。

単純な型コンストラクタ

単純な型で型コンストラクタを調べてみます。以下は、Intのカインドを調べる例です。

$ ghci
ghci> :kind Int
Int :: *

Intのような具体的な型がカインド「*」であることは、追加の型引数を取らないことを意味しています。

引数がある型コンストラクタ (引数が1つ)

引数がありパラメータ化されている方として代表的なものとしては、Maybe型があります。以下は、Maybe型のカインドを調べる例です。

$ ghci
ghci> :kind Maybe
Maybe :: * -> *

Maybeのような引数を1つ取る型のカインドは「* -> *」というようになります。Maybeでは、Maybe Intといった表記を見たことがあると思いますが、これはMaybeIntを引数に取っていることを意味します。

Maybeは欠損値に対応するために、値が存在するかもしれないことを表現するものであるため、Maybe Intは、Intが存在するかもしれないし、存在しないかもしれないということを表現します。

複数の引数がある型コンストラクタ (引数が2つ)

複数の引数を受け取る方もあり、代表的なものとしては、Either型があります。以下は、Either型のカインドを調べる例です。

$ ghci
ghci> :kind Either
Either :: * -> * -> *

Eitherのような引数を2つ取る型のカインドは「* -> * -> *」というようになります。Eitherでは、Either String Intといった表記を見たことがあると思いますが、これはEitherStringIntを引数に取っていることを意味します。

Eitherは、2つの異なる型の値のいずれかを含むことを表現するものであるため、Either String Intは、StringIntのいずれかということになります。例えば、エラー処理においてエラー文字列を返すか、成功した値を返すような場合に使用します。

まとめ

HaskellコンパイラであるGHC (Glasgow Haskell Compiler)のインタラクティブ対話型シェルのGHCiの主要なコマンドについて紹介しました。

本記事では、よく使うであろう代表的なコマンドについて紹介しています。Haskellでは、GHCiで各モジュールの関数を動作確認し、確認が終わったらGHCでコンパイルするという開発の流れが一般的です。

GHCiには様々なコマンドがありますが、主要なコマンドを把握しておくことは非常に役立ちますので参考にしてもらえればと思います。