Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Haskell Dictionary
  3. MODULE Basics

MODULE Basics

Haskell's module system organizes functions, types, and type classes into namespaces and lets you precisely control what is visible to the outside. One .hs file corresponds to one module. The module declaration states the module name and lists the symbols to export. In import statements, you can combine qualified for name-qualified access, hiding to exclude specific names, and as for aliases — letting you bring in only the symbols you need while avoiding name collisions.

module declaration syntax

SyntaxDescription
module ModName whereDeclares the module. Omitting the export list makes all top-level definitions public.
module ModName (f, g) whereExports only functions f and g. Symbols not in the list cannot be accessed from outside the module.
module ModName (T(..)) whereExports type T along with all of its constructors.
module ModName (T) whereExports only the type name T while hiding its constructors (the smart constructor pattern).
module ModName (module SubMod) whereRe-exports all public symbols of another module as-is.

import statement syntax

SyntaxDescription
import ModNameBrings all exported symbols of the module into scope.
import ModName (f, T(..))Brings only the specified symbols into scope.
import qualified ModName as MAllows only qualified references. Call symbols as M.f.
import ModName hiding (f)Brings everything into scope except f.
import ModName as MCreates an alias that lets you access symbols both with and without the qualifier.

Commonly used modules

ModuleKey exportsDescription
Data.Listsort, nub, group, intercalateExtended list manipulation functions not found in the standard Prelude.
Data.Map.StrictMap k v, fromList, lookup, insertProvides a balanced-tree-based associative array (dictionary). The convention is to import it qualified.
Data.SetSet a, fromList, member, unionProvides an ordered set with no duplicates. The convention is also to import it qualified.
Data.MaybefromMaybe, mapMaybe, isJustUtility functions for working with Maybe values.
Data.CharisAlpha, toUpper, ord, chrFunctions for classifying and converting characters.
System.IOhSetBuffering, Handle, BufferModeProvides buffering control and other file handle operations.
Control.Monadwhen, unless, forM_, replicateMHelper functions for working with monads.

Sample code

rgg_module_export.hs
-- rgg_module_export.hs — sample showing module definition and export control
-- Uses yakuza organizations as sample data
-- Demonstrates how to make symbols public or private in a module declaration
--
--   Compile and run:
--     ghc rgg_module_export.hs -o rgg_module_export && ./rgg_module_export

-- -----------------------------------------------
--  Sub-module equivalent definitions (simulated in a single file)
-- -----------------------------------------------

-- In a real project you would split this into a separate file and declare:
--   module Yakuza (Clan(..), makeClan, clanName, memberCount) where
-- Here everything is merged into Main for easy testing.

module Main where

import Data.List (intercalate, sortBy)
import Data.Ord  (comparing, Down(..))

-- -----------------------------------------------
--  Data type definitions
-- -----------------------------------------------

-- Data type representing a yakuza organization
-- The constructor is kept private; use the smart constructor to create values
data Clan = Clan
  { clanName    :: String   -- organization name
  , clanLeader  :: String   -- boss / chairman name
  , memberCount :: Int      -- number of members
  } deriving (Show)

-- -----------------------------------------------
--  Smart constructor (creates a value with validation)
-- -----------------------------------------------

-- Smart constructor that only creates a Clan when memberCount is >= 0
-- This function is exported instead of the raw Clan constructor
makeClan :: String -> String -> Int -> Maybe Clan
makeClan name leader count
  | count >= 0 = Just (Clan name leader count)
  | otherwise  = Nothing  -- invalid values are rejected as Nothing

-- -----------------------------------------------
--  Public functions
-- -----------------------------------------------

-- Returns a summary string for a Clan
summaryClan :: Clan -> String
summaryClan c =
  clanName c ++ " (" ++ clanLeader c ++ ") / Members: "
  ++ show (memberCount c)

-- Sorts clans by member count in descending order and returns their summaries
rankClans :: [Clan] -> [String]
rankClans clans =
  map summaryClan                         -- convert each Clan to a summary string
  $ sortBy (comparing (Down . memberCount)) clans  -- sort by member count descending

-- -----------------------------------------------
--  Entry point
-- -----------------------------------------------

main :: IO ()
main = do
  putStrLn "===== Omi Alliance — Affiliated Organizations ====="
  putStrLn ""

  -- Create Clan values using the smart constructor
  -- The raw Clan{..} constructor is treated as unavailable by design
  let clans =
        [ makeClan "Tojo Clan"        "Kazuma Kiryu"   25800
        , makeClan "Omi Alliance"     "Omi Ren"        31200
        , makeClan "Daigo Family"     "Daigo"           6400
        , makeClan "Dojima Family"    "Dojima Tsuyoki"  3200
        , makeClan "3rd Katsuki Clan" "Katsuki"         1100
        , makeClan "Majima Clan"      "Goro Majima"      980
        ]

  -- Unwrap Just values and discard Nothing
  let validClans = [ c | Just c <- clans ]

  -- Display ranking by member count descending
  putStrLn "--- Member Count Ranking ---"
  mapM_ (\(i, s) -> putStrLn $ show i ++ ": " ++ s)
        (zip [1..] (rankClans validClans))

  putStrLn ""
  putStrLn "\"If you live by the yakuza code, live it with conviction.\""
ghc rgg_module_export.hs -o rgg_module_export && ./rgg_module_export
[1 of 1] Compiling Main             ( rgg_module_export.hs, rgg_module_export.o )
Linking rgg_module_export ...
===== Omi Alliance — Affiliated Organizations =====

--- Member Count Ranking ---
1: Omi Alliance (Omi Ren) / Members: 31200
2: Tojo Clan (Kazuma Kiryu) / Members: 25800
3: Daigo Family (Daigo) / Members: 6400
4: Dojima Family (Dojima Tsuyoki) / Members: 3200
5: 3rd Katsuki Clan (Katsuki) / Members: 1100
6: Majima Clan (Goro Majima) / Members: 980

"If you live by the yakuza code, live it with conviction."
rgg_import_qualified.hs
-- rgg_import_qualified.hs — sample showing qualified import / hiding / as
-- Uses characters from Like a Dragon as sample data
-- Demonstrates using Data.Map.Strict and Data.Set with qualified imports
--
--   Compile and run:
--     ghc rgg_import_qualified.hs -o rgg_import_qualified && ./rgg_import_qualified

module Main where

-- Import Data.Map.Strict qualified as Map
-- Using fromList etc. without a qualifier would clash with Data.List, so qualified is the convention
import qualified Data.Map.Strict as Map

-- Import Data.Set qualified as Set
import qualified Data.Set as Set

-- Import only intercalate from Data.List (selective import to avoid name collisions)
import Data.List (intercalate)

-- Import only fromMaybe from Data.Maybe
import Data.Maybe (fromMaybe)

-- -----------------------------------------------
--  Data definitions
-- -----------------------------------------------

-- Manages each character's signature weapon in a Map
-- Map.fromList :: [(k, v)] -> Map k v
weaponMap :: Map.Map String String
weaponMap = Map.fromList
  [ ("Kazuma Kiryu",  "Bare hands (Brawler style)")
  , ("Goro Majima",   "Knife / bat (Mad Dog style)")
  , ("Shun Akiyama",  "Kicks (Like a Dragon style)")
  , ("Taiga Saejima", "Kusarigama (Slug style)")
  , ("Tatsuo Shinada","Handgun (Gunman style)")
  , ("Makoto Date",   "Knife (Capoeira style)")
  ]

-- Manages Tojo Clan and Omi Alliance members in Sets
-- Set.fromList :: [a] -> Set a
tojokaiMembers :: Set.Set String
tojokaiMembers = Set.fromList
  [ "Kazuma Kiryu", "Akira Nishikiyama", "Daigo Dojima", "Makoto Date", "Taiga Saejima" ]

omikaiMembers :: Set.Set String
omikaiMembers = Set.fromList
  [ "Omi Ren", "Goro Majima", "Tatsuo Shinada" ]

-- -----------------------------------------------
--  Map / Set operations
-- -----------------------------------------------

-- Looks up a character's signature weapon by name
-- Map.lookup :: Ord k => k -> Map k v -> Maybe v
getWeapon :: String -> String
getWeapon name =
  -- fromMaybe provides a default value in case lookup returns Nothing
  fromMaybe "Unknown" (Map.lookup name weaponMap)

-- Returns all members from both organizations (union)
-- Set.union :: Ord a => Set a -> Set a -> Set a
allMembers :: Set.Set String
allMembers = Set.union tojokaiMembers omikaiMembers

-- Returns characters not belonging to either organization (difference)
-- Set.difference :: Ord a => Set a -> Set a -> Set a
independents :: [String] -> Set.Set String
independents names =
  Set.difference (Set.fromList names) allMembers

-- -----------------------------------------------
--  Entry point
-- -----------------------------------------------

main :: IO ()
main = do
  putStrLn "===== Yakuza Database ====="
  putStrLn ""

  -- Display each character's weapon using Map
  putStrLn "--- Signature Weapons (Map.lookup) ---"
  let characters = Map.keys weaponMap
  mapM_ (\name -> putStrLn $ "  " ++ name ++ ": " ++ getWeapon name) characters
  putStrLn ""

  -- Display all members from both organizations using Set union
  putStrLn "--- All Members from Both Organizations (Set.union) ---"
  -- Set.toAscList :: Set a -> [a] converts the set to an ascending list
  putStrLn $ "  " ++ intercalate ", " (Set.toAscList allMembers)
  putStrLn ""

  -- Find characters not belonging to either organization
  putStrLn "--- Independent Characters (Set.difference) ---"
  let allChars = Map.keys weaponMap
  let loners   = independents allChars
  putStrLn $ "  " ++ intercalate ", " (Set.toAscList loners)
  putStrLn ""

  -- Check the size of the Map
  -- Map.size :: Map k v -> Int
  putStrLn $ "Registered characters: " ++ show (Map.size weaponMap)
  putStrLn "\"Life is a battle. Don't run from it.\""
ghc rgg_import_qualified.hs -o rgg_import_qualified && ./rgg_import_qualified
[1 of 1] Compiling Main             ( rgg_import_qualified.hs, rgg_import_qualified.o )
Linking rgg_import_qualified ...
===== Yakuza Database =====

--- Signature Weapons (Map.lookup) ---
  Kazuma Kiryu: Bare hands (Brawler style)
  Goro Majima: Knife / bat (Mad Dog style)
  Shun Akiyama: Kicks (Like a Dragon style)
  Taiga Saejima: Kusarigama (Slug style)
  Tatsuo Shinada: Handgun (Gunman style)
  Makoto Date: Knife (Capoeira style)

--- All Members from Both Organizations (Set.union) ---
  Akira Nishikiyama, Daigo Dojima, Goro Majima, Kazuma Kiryu, Makoto Date, Omi Ren, Taiga Saejima, Tatsuo Shinada

--- Independent Characters (Set.difference) ---
  Shun Akiyama

Registered characters: 6
"Life is a battle. Don't run from it."
rgg_module_hiding.hs
-- rgg_module_hiding.hs — sample showing import control with hiding and as
-- Uses the battle system from Like a Dragon as sample data
-- Demonstrates coexisting a custom function with a same-named Prelude function
--
--   Compile and run:
--     ghc rgg_module_hiding.hs -o rgg_module_hiding && ./rgg_module_hiding

module Main where

-- Import sort and intercalate from Data.List, but hide lookup
-- lookup exists in Prelude too, so we exclude it here to avoid ambiguity
import Data.List (sort, intercalate)

-- Import Data.Map.Strict qualified so its lookup does not clash with Prelude's lookup
import qualified Data.Map.Strict as Map

-- Import System.IO under the short alias IO (using as for renaming)
import qualified System.IO as IO

-- -----------------------------------------------
--  Data definitions
-- -----------------------------------------------

-- Type representing a Heat Action move
data HeatAction = HeatAction
  { haName   :: String   -- move name
  , haDamage :: Int      -- damage value
  , haStyle  :: String   -- style used
  } deriving (Show)

-- Manage move data in a Map
heatActions :: Map.Map String HeatAction
heatActions = Map.fromList
  [ ("Tiger Drop",
      HeatAction "Tiger Drop"      9800 "Brawler style")
  , ("Final Slugger",
      HeatAction "Final Slugger"   8500 "Like a Dragon style")
  , ("Wall Break",
      HeatAction "Wall Break"      7200 "Rush style")
  , ("Essence of Demon",
      HeatAction "Essence of Demon" 11000 "Dragon of Dojima style")
  , ("Raging Bind",
      HeatAction "Raging Bind"     9300 "Slug style")
  ]

-- -----------------------------------------------
--  Function definitions
-- -----------------------------------------------

-- Returns the top N moves sorted by damage value
-- sort is Data.List's sort (making it explicit that this is not from Prelude)
topHeatActions :: Int -> [HeatAction]
topHeatActions n =
  take n
  -- Sort in descending order by damage value (pass a comparison function to sort)
  $ reverse
  $ sort
  $ map snd (Map.toList heatActions)  -- extract HeatAction list from Map

-- Returns a display string for a HeatAction
showHA :: HeatAction -> String
showHA ha =
  haName ha ++ "  [" ++ haStyle ha ++ "]  Damage: " ++ show (haDamage ha)

-- -----------------------------------------------
--  Ord instance (required for sort)
-- -----------------------------------------------

instance Eq HeatAction where
  a == b = haDamage a == haDamage b

instance Ord HeatAction where
  compare a b = compare (haDamage a) (haDamage b)

-- -----------------------------------------------
--  Entry point
-- -----------------------------------------------

main :: IO ()
main = do
  -- IO.hSetBuffering is the same as System.IO.hSetBuffering (using the alias)
  IO.hSetBuffering IO.stdout IO.LineBuffering

  putStrLn "===== Heat Action Ranking ====="
  putStrLn ""

  -- Search for a specific move with Map.lookup (distinct from Prelude's lookup)
  putStrLn "--- Search move with Map.lookup ---"
  case Map.lookup "Essence of Demon" heatActions of
    Nothing -> putStrLn "  Move not found"
    Just ha -> putStrLn $ "  " ++ showHA ha
  putStrLn ""

  -- Display the top 3 moves by damage
  putStrLn "--- Damage TOP 3 ---"
  let top3 = topHeatActions 3
  mapM_ (\(i, ha) -> putStrLn $ "  " ++ show i ++ ": " ++ showHA ha)
        (zip [1..] top3)
  putStrLn ""

  -- Display all move names in ascending order (using Data.List.sort)
  putStrLn "--- All move names (ascending) ---"
  let names = sort (Map.keys heatActions)
  putStrLn $ "  " ++ intercalate " / " names
  putStrLn ""

  putStrLn "\"This is my Heat Action!\""
ghc rgg_module_hiding.hs -o rgg_module_hiding && ./rgg_module_hiding
[1 of 1] Compiling Main             ( rgg_module_hiding.hs, rgg_module_hiding.o )
Linking rgg_module_hiding ...
===== Heat Action Ranking =====

--- Search move with Map.lookup ---
  Essence of Demon  [Dragon of Dojima style]  Damage: 11000

--- Damage TOP 3 ---
  1: Essence of Demon  [Dragon of Dojima style]  Damage: 11000
  2: Tiger Drop  [Brawler style]  Damage: 9800
  3: Raging Bind  [Slug style]  Damage: 9300

--- All move names (ascending) ---
  Essence of Demon / Final Slugger / Raging Bind / Tiger Drop / Wall Break

"This is my Heat Action!"

Summary

In Haskell's module system, you declare a module name and its exported symbols with module ModName (export list) where. A common pattern is to hide constructors in the export list and expose only a smart constructor function that performs validation. In import statements, the convention is to use qualified ... as alias to enforce name-qualified access and prevent collisions — especially for Data.Map.Strict and Data.Set. You can also use hiding (symbol) to exclude a specific name from the import, which is useful when you want a custom function to coexist with a same-named Prelude function. For file I/O across multiple module files, see File read/write. For more on Data.Map.Strict, see Defining data types.

If you find any errors or copyright issues, please .