实例头中具有行类型的类型类实例?
Typeclass instance with row type in instance head?
当我在玩 PureScript 时,我发现我想写一个类型class Sync
来等待任意异步值在 Aff
monad 中解析。我写的类型class是这样的:
class Sync s eff a where
sync :: s -> Aff eff a
现在我想为 websocket 连接创建 Sync
实例,它将等待连接打开并可用于 reading/writing。我写的实例是这样的:
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,然后创建一个新类型。
class Sync s m a where
sync :: s -> m a
newtype WebSocketAff a = WebSocketAff (Aff (ws :: WEBSOCKET) a)
不幸的是,现在我又被困住了,因为我不知道有什么方法可以给 WebSocketAff
一个 MonadAff
的实例,原因与我一开始遇到的类似。
有没有什么技巧可以让我在不完全违背通用主义目的的情况下让它发挥作用?还是目前在 PureScript 中无法真正表达这种东西?
我在移动 ATM 上,所以我无法对此进行测试,但您尝试过使用 forall 吗?
instance syncConnection :: forall eff. Sync Connectionync Connection . . .
从编译器版本 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
当我在玩 PureScript 时,我发现我想写一个类型class Sync
来等待任意异步值在 Aff
monad 中解析。我写的类型class是这样的:
class Sync s eff a where
sync :: s -> Aff eff a
现在我想为 websocket 连接创建 Sync
实例,它将等待连接打开并可用于 reading/writing。我写的实例是这样的:
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,然后创建一个新类型。
class Sync s m a where
sync :: s -> m a
newtype WebSocketAff a = WebSocketAff (Aff (ws :: WEBSOCKET) a)
不幸的是,现在我又被困住了,因为我不知道有什么方法可以给 WebSocketAff
一个 MonadAff
的实例,原因与我一开始遇到的类似。
有没有什么技巧可以让我在不完全违背通用主义目的的情况下让它发挥作用?还是目前在 PureScript 中无法真正表达这种东西?
我在移动 ATM 上,所以我无法对此进行测试,但您尝试过使用 forall 吗?
instance syncConnection :: forall eff. Sync Connectionync Connection . . .
从编译器版本 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