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 . . .
上一篇: Typeclass instance with row type in instance head?
下一篇: Inferring general typeclass instance from a series of smaller ones?