Да. Это называется "стиль передачи словаря". Иногда, когда я делаю какие-то особенно сложные вещи, мне нужно отбросить класс типов и превратить его в словарь, потому что передача словаря является более мощной 1 , но часто довольно громоздкой, что делает концептуально простой код выглядящим довольно сложным. Иногда я использую стиль передачи словаря в языках, которые не являются Haskell, для имитации классов типов (но я узнал, что это обычно не такая хорошая идея, как кажется).
Конечно, всякий раз, когда есть разница в выразительной силе, есть компромисс. Хотя вы можете использовать данный API-интерфейс несколькими способами, если он написан с использованием DPS, API-интерфейс получает больше информации, если вы не можете. На практике это проявляется в Data.Set
том, что для Ord
каждого типа существует только один словарь. В Set
магазинах его элементы сортируются в соответствии с Ord
, и если вы строите набор с одного словаря, а затем вставить элемент , используя другую, как это было бы возможно с DPS, вы можете разбить Set
«s инвариантно и привести к аварии. Эта проблема уникальности может быть смягчена с помощью фантомного экзистенциальноготип, чтобы отметить словарь, но, опять же, ценой довольно немного раздражающей сложности в API. Это также проявляется почти таким же образом в Typeable
API.
Бит уникальности появляется не очень часто. Классы типов хороши в написании кода для вас. Например,
catProcs :: (i -> Maybe String) -> (i -> Maybe String) -> (i -> Maybe String)
catProcs f g = f <> g
который берет два «процессора», которые принимают входные данные и могут выдавать выходные данные, и объединяют их, сглаживая их Nothing
, должны быть записаны в DPS примерно так:
catProcs f g = (<>) (funcSemi (maybeSemi listSemi)) f g
По сути, нам снова пришлось прописать тип, в котором мы его используем, даже если мы уже прописали его в сигнатуре типа, и даже это было избыточно, потому что компилятор уже знает все типы. Поскольку существует только один способ создать данное значение Semigroup
для типа, компилятор может сделать это за вас. Это имеет эффект типа «сложный интерес», когда вы начинаете определять множество параметрических экземпляров и использовать структуру ваших типов для вычислений для вас, как в Data.Functor.*
комбинаторах, и это используется для deriving via
достижения большого эффекта, когда вы можете получить практически все «стандартная» алгебраическая структура вашего типа написана для вас.
И даже не заводите меня на MPTC и fundeps, которые возвращают информацию обратно к проверке типов и выводам. Я никогда не пытался преобразовать такую вещь в DPS - я подозреваю, что это потребовало бы передачи большого количества доказательств равенства типов - но в любом случае я уверен, что это будет намного больше работы для моего мозга, чем мне было бы удобно с.
-
1 U nless использовать reflection
в этом случае они становятся эквивалентными в силе - но reflection
также может быть обременительным для использования.