#haskell #existential-type #template-haskell #dynamic-dispatch
#haskell #экзистенциальный тип #шаблон-haskell #динамическая отправка
Вопрос:
Я смотрю на HaskellWiki> Экзистенциальный тип# Механизм динамической отправки.
И я думаю, в Template Haskell должен быть способ принять эту часть:
class Shape_ a where
...
type Radius = Double
data Circle = Circle Radius
instance Shape_ Circle where
...
и автоматически выводит эту часть:
-- derive the data type
data Shape = forall a. Shape_ a => Shape a
-- derive smart constructors similar to the original constructor
circle :: Radius -> Shape
circle r = Shape (Circle r)
Это было сделано в Template Haskell? Можно ли это сделать в TH? Можно ли сделать что-то подобное в простом старом Haskell без необходимости выписывать все интеллектуальные конструкторы вручную? Потребуется ли для этого специальный препроцессор, более мощный, чем TH?
Ответ №1:
Это определенно можно сделать с помощью шаблона Haskell. Очень мало того, что невозможно. Но я считаю, что написание шаблонного кода Haskell довольно болезненно.
С GHC 7.4 и расширением ConstraintKinds вы также можете абстрагировать его часть:
data Some :: (* -> Constraint) -> * where
Some :: forall cls a. cls a => a -> Some cls
type Shape = Some Shape_
instance Shape_ Shape where
perimeter (Some a) = perimeter a
area (Some a) = area a
shape :: Shape_ a => a -> Shape
shape = Some
Автоматизация этих объявлений экземпляров — это еще одна вещь, которую может сделать TH, и, насколько мне известно, только TH.
Комментарии:
1. Другими словами, «Да! Шаблон Haskell может это сделать! » 🙂 Спасибо за совет по ConstraintKinds, это довольно круто.
2. Да… Я бы показал вам код, если бы не упомянутая причина. Ручной анализ и построение АСТ — это очень весело.
Ответ №2:
Как насчет добавления метода в Shape_
класс с реализацией по умолчанию:
toShape :: a -> Shape
toShape = Shape
Для получения информации об уровне техники см. Exception
Класс и SomeException
тип данных.
Комментарии:
1. Я надеюсь на автоматически производные интеллектуальные конструкторы; это все равно потребует от меня написания
circle r = toShape (Circle r)
и т. Д.