implementation module htmlArrow
import StdFunc, StdList, StdString
import htmlFormlib
import StdArrow
startCircuit :: !(GecCircuit a b) !a !*HSt -> (!Form b,!*HSt)
startCircuit (HGC circuit) initval hst
# ((val,body),ch,hst) = circuit ((initval,[]),False,hst)
= ( {changed= ch
,value = val
,form = reverse (removedup body [])
},hst)
where
removedup [] _ = []
removedup [(id,body):rest] ids
| isMember id ids = removedup rest ids
| otherwise = [body: removedup rest [id:ids]]
:: GecCircuit a b
= HGC !((GecCircuitState a) -> GecCircuitState b)
:: *GecCircuitState a :== *((a, [(String,BodyTag)]), GecCircuitChanged, *HSt )
:: GecCircuitChanged :== Bool
instance Arrow GecCircuit where
arr fun = HGC fun`
where
fun` ((a,body),ch,hst) = ((fun a,body),ch,hst)
(>>>) (HGC gec_ab) (HGC gec_bc) = HGC (gec_bc o gec_ab)
first (HGC gec_ab) = HGC first`
where
first` (((a,c),prevbody),ch,hst)
# ((b,bodya),ch,hst) = gec_ab ((a,prevbody),ch,hst)
= (((b,c),bodya),ch,hst)
edit :: (FormId a) -> GecCircuit a a | iData a
edit formid = HGC mkApplyEdit`
where
mkApplyEdit` ((initval,prevbody),ch,hst)
# (na,hst) = mkApplyEditForm (Init,setFormId formid initval) initval hst
= ((na.value,[(formid.id,BodyTag na.form):prevbody]),ch||na.changed,hst) // propagate change
display :: (FormId a) -> GecCircuit a a | iData a
display formid = HGC mkEditForm`
where
mkEditForm` ((val,prevbody),ch,hst)
# (na,hst) = mkEditForm (Set,setFormId {formid & mode = Display} val) hst
= ((na.value,[(formid.id,BodyTag na.form):prevbody]),ch||na.changed,hst)
store :: (FormId s) -> GecCircuit (s -> s) s | iData s
store formid = HGC mkStoreForm`
where
mkStoreForm` ((fun,prevbody),ch,hst)
# (store,hst) = mkStoreForm (Init,formid) fun hst
= ((store.value,[(formid.id,BodyTag store.form):prevbody]),ch||store.changed,hst)
self :: (a -> a) !(GecCircuit a a) -> GecCircuit a a
self fun gecaa = feedback gecaa (arr fun)
feedback :: !(GecCircuit a b) !(GecCircuit b a) -> (GecCircuit a b)
feedback (HGC gec_ab) (HGC gec_ba) = HGC (gec_ab o gec_ba o gec_ab)
loops :: !(GecCircuit (a, b) (c, b)) -> GecCircuit a c | iData b
loops (HGC gec_abcb) = HGC loopForm
where
loopForm ((aval,prevbody),ch,hst)
# (bstore,hst) = mkStoreForm (Init,xsFormId "??" createDefault) id hst
# (((cval,bval),bodyac),ch,hst) = gec_abcb (((aval,bstore.value),prevbody),ch,hst)
# (bstore,hst) = mkStoreForm (Set,xsFormId "??" createDefault) (\_ -> bval) hst
= ((cval,bodyac),ch,hst)
(`bindC`) infix 0 :: !(GecCircuit a b) (b -> GecCircuit b c) -> (GecCircuit a c)
(`bindC`) (HGC gecab) bgecbc = HGC binds
where
binds ((a,abody),ach,hst)
# ((b,bbody),bch,hst) = gecab ((a,abody),ach,hst)
# (HGC gecbc) = bgecbc b
= gecbc ((b,bbody ++ abody),ach||bch,hst)
(`bindCI`) infix 0 :: !(GecCircuit a b) ((Form b) -> GecCircuit b c) -> (GecCircuit a c)
(`bindCI`) (HGC gecab) bgecbc = HGC binds
where
binds ((a,abody),ach,hst)
# ((b,bbody),bch,hst) = gecab ((a,abody),ach,hst)
# (HGC gecbc) = bgecbc {changed = bch, value = b, form = map snd bbody}
= gecbc ((b,bbody ++ abody),ach||bch,hst)
lift :: !(InIDataId a) ((InIDataId a) *HSt -> (Form b,*HSt)) -> GecCircuit a b
lift (Set,formid) fun = HGC fun`
where
fun` ((a,body),ch,hst)
# (nb,hst) = fun (setID formid a) hst
= ((nb.value,[(formid.id,BodyTag nb.form):body]),ch||nb.changed,hst)
lift (Init,formid) fun = HGC fun`
where
fun` ((a,body),ch,hst)
# (nb,hst) = fun (Init, setFormId formid a) hst
= ((nb.value,[(formid.id,BodyTag nb.form):body]),ch||nb.changed,hst)