While I was playing with PureScript, I found that I wanted to write a typeclass Sync
that would wait for arbitrary asynchronous values to resolve in the Aff
monad. The typeclass I wrote looked like this:
class Sync s eff a where
sync :: s -> Aff eff a
Now I wanted to create Sync
instance for a websocket connection, which would wait until the connection was open and available for reading/writing. The instance I wrote looked like this:
instance syncConnection :: Sync Connection (ws :: WEBSOCKET | eff) Unit where
sync (Connection socket) =
makeAff $ \fail continue ->
set socket.onopen $ \_ ->
continue unit
However, I got the following type error:
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.
Coming from Haskell, this makes sense to me—it mirrors situations where I would need to enable the FlexibleInstances
extension, which PureScript does not seem to support, either—but I’m left wondering if I can achieve the genericism I want at all.
I thought that perhaps I could tweak my Sync
class, then just create a newtype.
class Sync s m a where
sync :: s -> m a
newtype WebSocketAff a = WebSocketAff (Aff (ws :: WEBSOCKET) a)
Unfortunately, now I’m stuck yet again because I don’t know of any way to give WebSocketAff
an instance of MonadAff
for similar reasons to the ones I encountered at the beginning.
Are there any tricks I could use to get this to work without defeating the purpose of the genericism entirely? Or is that sort of thing currently not really expressible within PureScript?