2015-10-24 7 views
4

Я пытаюсь собрать этот маленький кусок кода.Полиморфная инструкция в 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 

Если вместо «a» в RFNewEvent вместо «a» вместо «a» используется «Number», тогда все компилируется нормально. Но как только я пойду «навсегда». и заменить «Число» на «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. now on newEvent)

Возможно, я сделал ошибку.

Общая цель - имитировать интерфейс SodiumFRP, используя Free Monad. Затем подключите существующую библиотеку JavaScript FRP, которая работает с Sodium через FFI при интерпретации Free Monad.

Возможно ли это?

+1

Я подозреваю, что вы хотите квантор существования, а не универсальный квантор? Вы видели «purescript-exist»? –

+0

Нет, я не видел purescript-существует. Теперь посмотрим на это. Хотя, возможно, я ошибся в своем дизайне. – clinux

+1

@ Phil Freeman. Да, вы пишете. purescript-exists позволяет определить «образец». (следующая часть была застряла) – clinux

ответ

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 

Edit

также попробовать purescript-существует. Делает возможным определить «образец»

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 

Спасибо Фил Фримен за ваш комментарий.