Typeclass instance with row type in instance head?

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?


Since compiler version 0.10.3 you are allowed to use rows in the instance head as long as the row is determined via a FunDep:

eg

class Sync s eff a | s -> eff where -- FunDep here: eff is determinded via s
  sync :: s -> Eff eff a

data ConsoleSync = ConsoleSync

instance syncWithConsole :: Sync ConsoleSync (console :: CONSOLE | eff) Unit where
  sync _ = log "hello"

foo :: ∀ eff. Eff (console :: CONSOLE | eff) Unit
foo = sync ConsoleSync

Release Notes v0.10.3: https://github.com/purescript/purescript/releases/tag/v0.10.3


我在我的移动ATM上,所以我无法测试这个,但是您是否尝试使用forall?

instance syncConnection :: forall eff. Sync Connectionync Connection . . .

链接地址: http://www.djcxy.com/p/43542.html

上一篇: 约束约束的论点

下一篇: Typeclass实例在实例头部有行类型?