Иерархия модулей
Модулям можно придать иерархическую структуру. Каждый модуль может иметь несколько подмодулей, которые в свою очередь также могут содержать подмодули. Давайте разделим наш модуль Geometry таким образом, чтобы в него входили три подмодуля, по одному на каждый тип объекта.
Сначала создадим папку с именем Geometry. В этой папке мы разместим три файла: Sphere.hs, Cuboid.hs и Cube.hs. Посмотрим, что должно находиться в каждом файле.
Вот содержимое файла Sphere.hs:
module Geometry.Sphere
( volume
, area
) where
volume :: Float –> Float
volume radius = (4.0 / 3.0) * pi * (radius 3)
area :: Float –> Float
area radius = 4 * pi * (radius 2)
Файл Cuboid.hs выглядит так:
module Geometry.Cuboid
( volume
, area
) where
volume :: Float –> Float –> Float –> Float
volume a b c = rectArea a b * c
area :: Float –> Float –> Float –> Float
area a b c = rectArea a b * 2 + rectArea a c * 2 + rectArea c b * 2
rectArea :: Float –> Float –> Float
rectArea a b = a * b
А вот и содержимое файла Cube.hs:
module Geometry.Cube
( volume
, area
) where
import qualified Geometry.Cuboid as Cuboid
volume :: Float –> Float
volume side = Cuboid.volume side side side
area :: Float –> Float
area side = Cuboid.area side side side
Обратите внимание, что мы поместили файл Sphere.hs в папку с именем Geometry и определили имя модуля как Geometry.Sphere. То же самое мы сделали для куба и параллелепипеда. Также отметьте, что во всех трёх модулях определены функции с одинаковыми именами. Мы вправе так поступать, потому что функции находятся в разных модулях.
Итак, если мы редактируем файл, который находится на одном уровне с папкой Geometry, то запишем:
import Geometry.Sphere
после чего сможем вызывать функции area и volume, которые вычислят площадь и объём сферы. Если нам потребуется использовать несколько наших модулей, мы должны выполнить квалифицированный импорт, потому что они экспортируют функции с одинаковыми именами. Делаем так:
import qualified Geometry.Sphere as Sphere
import qualified Geometry.Cuboid as Cuboid
import qualified Geometry.Cube as Cube
Затем мы сможем вызывать функции Sphere.area, Sphere.volume, Cuboid.area и т. д., и каждая функция вычислит площадь или объём соответствующего объекта.
В следующий раз, когда вы поймаете себя за написанием огромного файла с кучей функций, попытайтесь выяснить, какие функции служат некоей общей цели, и можно ли включить их в отдельный модуль.
Позднее при написании программы со схожей функциональностью вы сможете просто импортировать свой модуль.