Purescript中免费Monad中的多态指令

时间:2015-10-24 13:53:50

标签: purescript free-monad

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

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”,那么一切都编译得很好。但是,当我走的时候“fo。”。并将“数字”替换为“a”,不再编译。

我收到以下错误消息

Cannot unify type
  a1
with type
  a0

有谁知道如何使这项工作?

我正在使用0.5.0版本的purescript-free。

修改

如果我使用以下

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

并将其替换为RFNewEvent,然后它将编译。但我最终得到了一个不受欢迎的newEvent类型签名。

newEvent :: Reactive NewEventData
newEvent = liftFC $ RFNewEvent id

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

我可能犯了一个错误。

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

这可能吗?

1 个答案:

答案 0 :(得分:3)

以下代码现在编译并具有" 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

感谢Phil Freeman的评论。