Reputation: 3074
I'm trying to get this small piece of code to compile.
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
If I instead use "Number" instead of "a" in RFNewEvent, then everything compiles fine. But the moment I go "forall a." and replace "Number" with "a" it no longer compiles.
I get the following error message
Cannot unify type
a1
with type
a0
Does anyone know how to make this work?
I'm using version 0.5.0 of purescript-free.
Edit
If I use the following
data NewEventData = NewEventData forall a. Tuple (Event a) (a -> Reactive Unit)
and substitute it into RFNewEvent, then it will compile. But I end up with an undesired type signature for newEvent.
newEvent :: Reactive NewEventData
newEvent = liftFC $ RFNewEvent id
Which lets me create an event, but lets me shoot different event values to the event stream instead of the same type of value. (missing forall a. now on newEvent)
I might of made a mistake.
The overall goal is to simulate SodiumFRP's interface using a Free Monad. Then plug in an existing JavaScript FRP library that works similar to Sodium via FFI when interpreting the Free Monad.
Is this possible?
Upvotes: 3
Views: 223
Reputation: 3074
The following code now compiles and has the desired type signature for "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
Edit
Also trying out purescript-exists. Makes it possible to define "sample"
RFSample gets added to 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
Thank you Phil Freeman for your comment.
Upvotes: 2