В Haskell этот шаблон OO переводит почти напрямую, вам нужен только словарь.Обратите внимание, что прямой перевод не очень хорошая идея.Попытка навязать концепцию ОО в Haskell является своего рода обратным словом, но вы просили об этом, вот оно.
Интерфейс окна
В Haskell есть классы, которые имеютвсе функциональные возможности интерфейса, а затем некоторые.Поэтому мы будем использовать следующий класс Haskell:
class Window w where
draw :: w -> IO ()
description :: w -> String
Абстрактный класс WindowDecorator
Этот вариант немного сложнее, поскольку в Haskell нет понятия наследования.Обычно мы вообще не предоставляем этот тип и позволяем декораторам напрямую реализовывать Window
, но давайте полностью последуем примеру.В этом примере WindowDecorator
- это окно с конструктором, принимающим окно, давайте дополним его функцией, дающей оформленное окно.
class WindowDecorator w where
decorate :: (Window a) => a -> w a
unDecorate :: (Window a) => w a -> a
drawDecorated :: w a -> IO ()
drawDecorated = draw . unDecorate
decoratedDescription :: w a -> String
decoratedDescription = description . unDecorate
instance (WindowDecorator w) => Window w where
draw = drawDecorated
description = decoratedDescription
Обратите внимание, что мы предоставляем реализацию по умолчанию Window
,его можно заменить, и все экземпляры WindowDecorator
будут иметь вид Window
.
Декораторы
Создание декораторов может быть выполнено следующим образом:
data VerticalScrollWindow w = VerticalScrollWindow w
instance WindowDecorator VerticalScrollWindow where
decorate = VerticalScrollWindow
unDecorate (VerticalScrollWindow w ) = w
drawDecorated (VerticalScrollWindow w ) = verticalScrollDraw >> draw w
data HorizontalScrollWindow w = HorizontalScrollWindow w
instance WindowDecorator HorizontalScrollWindow where
decorate = HorizontalScrollWindow
unDecorate (HorizontalScrollWindow w .. ) = w
drawDecorated (HorizontalScrollWindow w ..) = horizontalScrollDraw >> draw w
Завершение
Наконец, мы можем определить некоторые окна:
data SimpleWindow = SimpleWindow ...
instance Window SimpleWindow where
draw = simpleDraw
description = simpleDescription
makeSimpleWindow :: SimpleWindow
makeSimpleWindow = ...
makeSimpleVertical = VerticalScrollWindow . makeSimpleWindow
makeSimpleHorizontal = HorizontalScrollWindow . makeSimpleWindow
makeSimpleBoth = VerticalScrollWindow . HorizontalScrollWindow . makeSimpleWindow