sphereArea radius = 4 * pi * (radius 2)
cubeVolume :: Float –> Float
cubeVolume side = cuboidVolume side side side
cubeArea :: Float –> Float
cubeArea side = cuboidArea side side side
cuboidVolume :: Float –> Float –> Float –> Float
cuboidVolume a b c = rectArea a b * c
cuboidArea :: Float –> Float –> Float –> Float
cuboidArea a b c = rectArea a b * 2 + rectArea a c * 2 + rectArea c b * 2
rectArea :: Float –> Float –> Float
rectArea a b = a * b
Довольно стандартная геометрия, но есть несколько вещей, на которые стоит обратить внимание. Так как куб – это разновидность параллелепипеда, мы определили его площадь и объём, трактуя куб как параллелепипед с равными сторонами. Также мы определили вспомогательную функцию rectArea
, которая вычисляет площадь прямоугольника по его сторонам. Функция очень проста – она просто перемножает стороны. Заметьте, мы используем функцию rectArea
в функциях модуля (а именно в функциях cuboidArea
и cuboidVolume
), но не экспортируем её, так как хотим создать модуль для работы только с трёхмерными объектами.
При создании модуля мы обычно экспортируем только те функции, которые служат интерфейсом нашего модуля, и скрываем реализацию. Использующий наш модуль человек ничего не должен знать о тех функциях, которые мы не экспортируем. Мы можем полностью их поменять или удалить в следующей версии (скажем, удалить определение функции rectArea
и просто использовать умножение), и никто не будет против – в первую очередь потому, что эти функции не экспортируются.
Чтобы использовать наш модуль, запишем:
import Geometry
Файл
Иерархия модулей
Модулям можно придать иерархическую структуру. Каждый модуль может иметь несколько подмодулей, которые в свою очередь также могут содержать подмодули. Давайте разделим наш модуль Geometry
таким образом, чтобы в него входили три подмодуля, по одному на каждый тип объекта.
Сначала создадим папку с именем
Вот содержимое файла
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)
Файл
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
А вот и содержимое файла
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
Обратите внимание, что мы поместили файл Geometry.Sphere
. То же самое мы сделали для куба и параллелепипеда. Также отметьте, что во всех трёх модулях определены функции с одинаковыми именами. Мы вправе так поступать, потому что функции находятся в разных модулях.
Итак, если мы редактируем файл, который находится на одном уровне с папкой
import Geometry.Sphere
после чего сможем вызывать функции area
и volume
, которые вычислят площадь и объём сферы. Если нам потребуется использовать несколько наших модулей, мы должны выполнить квалифицированный импорт, потому что они экспортируют функции с одинаковыми именами. Делаем так:
import qualified Geometry.Sphere as Sphere
import qualified Geometry.Cuboid as Cuboid