Я пытаюсь написать что-то, что похоже на "типы ранга 2", но вместо ограничений. (Или, может быть, неверно полагать, что изменение ->
в определении "типов ранга 2" на =>
имеет смысл; пожалуйста, отредактируйте вопрос, если считаете, что лучше терминологии).
Во-первых, Подходящий
класс типов (из Data.Suitable , основа rmonad) может использоваться для обозначения типов значений, которые могут В этом вопросе я буду использовать
Suitable m a
, чтобы обозначить, что значение a
может использоваться как значение для некоторых функций монады m
(в частности, если m
- это DSL, тогда его значения обычно a
, которые подходят), например
class PrintSuitable m where
printSuitable :: Suitable m a => a -> m ()
См. Верхний комментарий для RMonad [ ссылка ] и его источник для примера того, как использовать "Подходит". Например, один может определить Подходящий m (Карта a b)
и распечатать количество элементов на карте.
цель : Теперь у меня есть преобразователь монад MyMonadT
, и я хочу сделать MyMonadT m
экземпляром PrintSuitable
всякий раз, когда m
- это экземпляр PrintSuitable
.
Мотивация ограничений ранга 2 : Проблема в том, что тип a
вводится в отношении функции printSuitable
, т.е. не появляется в классе
подпись. Поскольку можно добавить ограничения только к сигнатуре класса
(дополнительные ограничения для реализации функции экземпляра
недопустимы), имеет смысл сказать кое-что обо всех a
в подпись класса (строка 2 ниже).
Ниже показан предполагаемый код.
instance (PrintSuitable m, MonadTrans t,
(forall a. Suitable (t m) a => Suitable m a), -- rank 2 constraint
) => PrintSuitable (t m) where
printSuitable = lift ...
-- MyMonadT doesn't change what values are Suitable, hence the rank 2 expression,
-- (forall a. Suitable (t m) a => Suitable m a) should hold true
data instance Constraints (MyMonadT m) a =
Suitable m a => MyMonadT_Constraints
instance Suitable m a => Suitable (MyMonadT m) a where -- the important line
constraints = MyMonadT_Constraints
instance MonadTrans MyMonadT where ...
-- now, MyMonadT m is a PrintSuitable whenever m is a PrintSuitable
-- the manual solution, without using MonadTrans, looks roughly like this
instance PrintSuitable m => PrintSuitable (t m) where
printSuitable a = withResConstraints $ \MyMonadT_Constraints -> ...
указанное ограничение говорит, что все, что подходит в (t m)
, подходит в m
. Но, конечно, это неверный Haskell; как можно кодировать функциональный эквивалент?
Заранее спасибо !!!