Используя Haskell, я хотел бы сгруппировать функции вместе, как если бы я использовал объектную ориентацию в других языках. Конкретно следуя ответу на этот вопрос
Поддерживает ли Haskell объектно-ориентированное программирование
допустим, у меня есть тип
data Class = Obj { a :: Int -> Int, b :: Int -> Int }
а теперь я хочу определить несколько других функций (как бы методов), производных от a и b. Один из способов сделать это - определить что-то вроде
c :: Class -> Int -> Int
c obj x = myb (mya x)
where mya = a obj
myb = b obj
d :: Class -> Int -> Int
d obj x = myb (myc x)
where myb = b obj
myc = c obj
Однако это означает, что в каждом шаблоне регулярное выражение мне нужно явно указать (в предложении where), какие другие функции я использую. У меня вопрос: есть ли более короткий способ добиться этого?
Естественный способ «сгруппировать» функции и их данные в Haskell - это модули.
Какая именно цель? Какое-то наследство? Возможно, вас заинтересует Почему я должен предпочесть композицию наследованию?? Возможно, вы могли бы указать пример использования этого шаблона. Выполнение в Haskell вещей, подобных ООП, может иметь несколько целей; Вы проводите собственное исследование шаблонов программирования или пытаетесь повторно использовать шаблоны, уже имеющиеся у вас за поясом, вместо того, чтобы изучать новые?
Хотя программирование объектно-ориентированныйможет может быть достигнуто в Haskell (в том смысле, что вы можете сделать что-то довольно похожее), обычно не стоит менять парадигму.
Пример использования такой: в зависимости от набора параметров у меня есть две основные функции перезаписи слов. Используя их, я могу определить производные функции перезаписи и в конечном итоге получить функцию, вычисляющую нормальную форму. Теперь предполагается, что тип представляет два основных правила перезаписи (или, что эквивалентно, параметры), а затем все производные правила принадлежат одним и тем же параметрам.
Возможно, мне не стоило упоминать об объектной ориентации, потому что теперь все сигналы тревоги срабатывают еще до того, как кто-либо прочитает то, что я на самом деле спрашиваю.
Вот тот же вопрос без упоминания об ориентации объекта: stackoverflow.com/questions/49897341/…


Если ваша цель - просто не печатать слишком много, вы можете использовать расширение RecordWildCards:
{-# LANGUAGE RecordWildCards #-}
data Class = Obj { a :: Int -> Int, b :: Int -> Int }
f :: Class -> Int -> Int
f Obj{..} x = a x + b x
Тогда вы можете использовать это так: f (Obj id id) 10 == 20
Обратите внимание, что это затеняет фактические «средства доступа к полям», поэтому это не сработает, если вы по-прежнему хотите использовать их в той же функции по какой-то причине.
Без расширений всегда можно просто написать
f (Obj a b) x = a x + b x
(Типы записей могут быть сопоставлены с шаблоном с использованием обычного синтаксиса конструктора).
Спасибо! Это решает вопрос, но только для функций a и b. Могу ли я также избавиться от "where myb = b obj"?
@StefanWitzel Я не понимаю, о чем ты? myb = b obj здесь не нужен.
При определении функции d выше я использовал функцию c. Ваше решение не записывать mya и myb зависит от того факта, что это поля класса, поэтому избежать записи myc не получится.
каждое "регулярное выражение"?