Typeclass实例在实例头部有行类型?

当我在使用PureScript时,我发现我想写一个类别类别Sync ,它会等待任意异步值在Aff monad中解析。 我写的类型类似这样:

class Sync s eff a where
  sync :: s -> Aff eff a

现在我想为websocket连接创建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中目前不能表达的那种东西?


由于编译器版本为0.10.3,只要该行是通过FunDep确定的,就可以使用实例头中的行:

例如

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

发行说明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/43541.html

上一篇: Typeclass instance with row type in instance head?

下一篇: Inferring general typeclass instance from a series of smaller ones?