Purescript 中的 Free Monad 中的多态指令

Polymorphic instruction in Free Monad in Purescript

我正在尝试编译这一小段代码。

module Sodium where

import Prelude
import Control.Monad.Free
import Data.Coyoneda
import Data.Tuple

data ReactiveF more
  = RFNewEvent (forall a. (Tuple (Event a) (a -> Reactive Unit) -> more))

type Reactive a = FreeC ReactiveF a

data Event a = Event a

newEvent :: forall a. Reactive (Tuple (Event a) (a -> Reactive Unit))
newEvent = liftFC $ RFNewEvent id

如果我在 RFNewEvent 中使用 "Number" 而不是 "a",那么一切都可以正常编译。但是当我去 "forall a." 并将 "Number" 替换为 "a" 时,它不再编译。

我收到以下错误消息

Cannot unify type
  a1
with type
  a0

有谁知道如何进行这项工作?

我使用的是 purescript-free 0.5.0 版。

编辑

如果我使用下面的

data NewEventData = NewEventData forall a. Tuple (Event a) (a -> Reactive Unit)

代入RFNewEvent,即可编译。但是我最终得到了一个不需要的 newEvent 类型签名。

newEvent :: Reactive NewEventData
newEvent = liftFC $ RFNewEvent id

这让我可以创建一个事件,但可以让我将不同的事件值发送到事件流,而不是相同类型的值。 (缺少所有 a. 现在在 newEvent 上)

我可能弄错了。

总体目标是使用 Free Monad 模拟 SodiumFRP 的界面。然后在解释 Free Monad 时通过 FFI 插入一个现有的 JavaScript FRP 库,它的工作方式类似于 Sodium。

这可能吗?

以下代码现在可以编译并具有 "newEvent"

所需的类型签名
module FRP.Sodium where

import Prelude
import Control.Monad.Free
import Data.Coyoneda
import Data.Tuple

data ReactiveF more
  = RFNewEvent (NewEventData -> more)

type Reactive a = FreeC ReactiveF a

data NewEventData = NewEventData forall a. Tuple (Event a) (a -> Reactive Unit)

data Event a
  = ENever
  | EMerge (Event a) (Event a)
  | EFilterJust (Event (Maybe a))
  | ECoalesce (a -> a -> a) (Event a)
  | EOnce (Event a)
  | ESplit (Event (Array a))
  | EVar Int

data Behaviour a = BVar Int

extractNewEventData :: forall a. NewEventData -> (Tuple (Event a) (a -> Reactive Unit))
extractNewEventData (NewEventData x) = x

newEvent :: forall a. Reactive (Tuple (Event a) (a -> Reactive Unit))
newEvent = map extractNewEventData $ liftFC $ RFNewEvent id

编辑

还尝试使用 purescript-exists。可以定义 "sample"

RFSample 被添加到 ReactiveF ...

.
.
.
data ReactiveF more
  = RFNewEvent (NewEventData -> more)
  | RFSample (SampleData more)
.
.
.
data SampleDataF more a = SampleDataF (Behaviour a) (a -> more)
type SampleData more = Exists (SampleDataF more)

sample :: forall a. Behaviour a -> Reactive a
sample beh = liftFC $ RFSample $ mkExists $ SampleDataF beh id

感谢菲尔·弗里曼的评论。