Играя с PureScript, я обнаружил, что хочу написать класс типов Sync
, который будет ждать разрешения произвольных асинхронных значений в монаде Aff
. Написанный мной класс типов выглядел так:
class Sync s eff a where
sync :: s -> Aff eff a
Теперь я хотел создать Sync
экземпляр для соединения через веб-сокет, который будет ждать, пока соединение не будет открыто и доступно для чтения / записи. Написанный мною экземпляр выглядел так:
instance syncConnection :: Sync Connection (ws :: WEBSOCKET | eff) Unit where
sync (Connection socket) =
makeAff $ \fail continue ->
set socket.onopen $ \_ ->
continue unit
Однако я получил следующую ошибку типа:
Type class instance head is invalid due to use of type
( ws :: WEBSOCKET
| eff
)
All types appearing in instance declarations must be of the form T a_1 .. a_n, where each type a_i is of the same form.
Исходя из Haskell, это имеет для меня смысл - это отражает ситуации, когда мне нужно было бы включить расширение FlexibleInstances
, которое PureScript, похоже, тоже не поддерживает, - но мне остается только гадать, смогу ли я вообще достичь желаемого обобщения.
Я подумал, что, возможно, я смогу настроить свой Sync
класс, а затем просто создать новый тип.
class Sync s m a where
sync :: s -> m a
newtype WebSocketAff a = WebSocketAff (Aff (ws :: WEBSOCKET) a)
К сожалению, сейчас я снова застрял, потому что не знаю способа дать WebSocketAff
экземпляр MonadAff
по причинам, аналогичным тем, с которыми я столкнулся в начале.
Есть ли какие-нибудь уловки, которые я мог бы использовать, чтобы заставить это работать, не уничтожая полностью цель дженеризма? Или такие вещи в настоящее время невозможно выразить в PureScript?