Учитывая эту оболочку вокруг целых чисел:
newtype MyProxy a = MyProxy Int
mkProxy :: Int -> MyProxy a
mkProxy a = MyProxy a
addProxy :: MyProxy a -> MyProxy a -> MyProxy a
addProxy (MyProxy a1) (MyProxy a2) = MyProxy $ a1+a2
Я могу выполнить следующее:
a = mkProxy 1
b = mkProxy 2
c = addProxy a b
потому что параметры фантома будут унифицированы. Но я хочу предотвратить эту унификацию и вызвать ошибку типа в строке c
.
Монада ST использует типы ранга 2 для достижения аналогичного эффекта. Вероятно, я мог бы сделать что-то подобное, изменив тип addProxy
. Но я специально не хочу этого делать. Я хочу как-то аннотировать переменную типа a
, чтобы предотвратить ее унификацию при вызове addProxy
.
Возможно ли это в Haskell? Есть ли причина, по которой такой вариант может быть опасен?
Редактировать:
Позвольте мне остановиться на частичном решении (требующем -XScopedTypeVariables
). Я могу переписать код выше как:
c :: forall a1 a2. MyProxy a1
c = addProxy a b
where
a = mkProxy 1 :: MyProxy a1
b = mkProxy 2 :: MyProxy a2
Это правильно вызывает ошибку типа c
, потому что a1
и a2
не могут быть объединены. Но у этого есть два недостатка: a
и b
нельзя определить на верхнем уровне; и вы должны явно указать результирующий тип mkProxy
.
Можно ли исправить эти недостатки?