モジュール

このページでは,Haskell におけるモジュールシステムについて説明します.

モジュール

Haskell の関数や型などは,モジュール (module) という単位にまとめられます. 標準で定義されているモジュールには,Data.Char モジュール,System.IO モジュールなどがあります. Prelude モジュールもその一つで,putStrLn 関数や print 関数を始めとする最も基本的な関数や型が定義されています.

標準モジュール

標準で定義されているモジュールには,次のようなものがあります.

Haskell 98Haskell 2010説明
PreludePrelude基本的な関数や型
RatioData.Ratio有理数
ComplexData.Complex複素数
NumericNumeric数値
IxData.Ixインデックス
ArrayData.Array配列
ListData.Listリスト
MaybeData.MaybeMaybe
CharData.Char文字
MonadControl.Monadモナド
IOSystem.IO入出力
DirectorySystem.Directoryディレクトリ
SystemSystem.Environment環境
TimeSystem.Time時間
LocaleSystem.Localeロケール
CPUTimeSystem.CPUTimeCPU 時間
RandomSystem.Random乱数

例えば,モジュール Data.List に定義されている関数 sort を利用するには,次のように書きます.

import Data.List

main = do print $ sort [2, 1, 3]            -- 出力: [1, 2, 3]
          print $ Data.List.sort [2, 1, 3]  -- 出力: [1, 2, 3]

キーワード import で始まる宣言はインポート宣言と呼ばれます. インポートするモジュールが複数ある場合,宣言はモジュールごとに書く必要があります.

モジュール Data.List からインポートされた sort には,sort または Data.List.sort と書くことでアクセスできます. 中置演算子 . と誤解されるため,Data.List.sortData . List . sort のように書くことはできません.

モジュールの作成

次の Geometry.hs は自作のモジュール Geometry を定義したものです. Main.hs ではモジュール Geometry をインポートしています.

-- ファイル: Geometry.hs

module Geometry where

data Shape = Tri { base, height:: Double }
           | Rect { width, height :: Double }

area :: Shape -> Double
area (Tri x y)  = x * y / 2
area (Rect x y) = x * y
-- ファイル: Main.hs

import Geometry

main = do print $ width (Rect 3 4)   -- 出力: 3.0
          print $ height (Rect 3 4)  -- 出力: 4.0
          print $ area (Tri 3 4)     -- 出力: 6.0
          print $ area (Rect 3 4)    -- 出力: 12.0

今回の Geometry.hs のように,モジュール定義はモジュール名と同名のファイルに保存する必要があります. また,モジュール名は英字の大文字で始める必要があります.

エクスポートリスト

モジュール定義の冒頭を次のように書くことで,エクスポートするエンティティを選択できます.

module Geometry(Shape(Tri, Rect), area) where

モジュール名直後の (Shape(Tri, Rect), area) はエクスポートリストと呼ばれ,エクスポートするエンティティをここに列挙します. エクスポートリストを省略した場合は,すべてのエンティティがエクスポートされます.

記述エクスポートの対象
module Geometry whereすべてのエンティティ
module Geometry(Shape) where型構成子 Shape
module Geometry(area) where関数 area
module Geometry(Shape, area) where型構成子 Shape,関数 area

型構成子,型クラスは,それに属するデータ構成子,フィールド,メンバ関数のエクスポートの有無も含めて記述します.

記述エクスポートの対象
Shape型構成子 Shape
Shape(Tri, Rect)型構成子 Shape, データ構成子 Tri, Rect
Shape(Tri, base, height)型構成子 Shape, データ構成子 Tri, フィールド base, height
Shape(..)型構成子 Shape とそのデータ構成子,フィールドすべて

また,次のように書くと,モジュール Numeric からインポートした内容を,モジュール Geometry で一緒にエクスポートできます.

module Geometry(module Geometry, module Numeric) where
import Numeric

インポート宣言

モジュールをインポートする側でも,インポート宣言を次のように書くことで,インポートするエンティティを選択できます. モジュール名直後のインポートリストの書き方は,エクスポートリストと同じです.

import Geometry(Shape(Tri, base), area)

main = do print $ area (Tri 3 4)    -- 可
          print $ area (Rect 3 4)   -- 不可
          print $ base (Tri 3 4)    -- 可
          print $ height (Tri 3 4)  -- 不可

他に,インポート宣言は次のような書き方ができます.

記述参照可能な名前説明
import Mx, y, M.x, M.yすべてのエンティティをインポート
import M(x)x, M.xエンティティ x のみインポート
import M hiding (x)y, M.yエンティティ x 以外をインポート
import qualified MM.x, M.yモジュール名による修飾を必須化する
import M as Nx, y, N.x, N.yモジュール名 M を N と置き換える

Prelude モジュール

Prelude モジュールは,最も基本的な関数や型などが定義されたモジュールです. インポート宣言を書かなくても,Prelude モジュールは暗黙のうちにインポートされます.

Prelude モジュールで提供されている関数等の一部をインポートしたくない場合は,次のようにインポート宣言を書きます.

import Prelude hiding (take, length)  -- Prelude の take, length を隠蔽

Main モジュール

モジュール名の記述がないファイルは,Main モジュールの記述として扱われます. 例として,次のような .hs ファイルが表すプログラムを考えます.

main = prtStrLn "hello, world"

このプログラムは,次のように記述される Main モジュールの頭部を省略したものと見なされます.

module Main(main) where
    main = prtStrLn "hello, world"

モジュールの階層化

標準モジュールの Data.List, System.IO のように,モジュールに階層を持たせることができます.

自作のモジュール Geometry を階層に入れて Data.Geometry にするには,いままで Geometry と記述していた箇所をすべて Data.Geometry に書き直します. さらに,ファイル Geometry.hs をディレクトリ Data に移動します.

module Data.Geometry where

-- 後略
import Data.Geometry

main = print $ area (Rect 3 4)   -- 出力: 12.0