Skip to content

Commit c736cf9

Browse files
authored
Merge pull request #19 from natefaubion/more-effectfn
Use more EffectFn
2 parents 25a3695 + 0cd9a7c commit c736cf9

File tree

7 files changed

+252
-292
lines changed

7 files changed

+252
-292
lines changed

src/Halogen/VDom.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ module Halogen.VDom
44
, module Types
55
) where
66

7-
import Halogen.VDom.DOM (VDomMachine, VDomStep, VDomSpec(..), buildVDom) as DOM
7+
import Halogen.VDom.DOM (VDomSpec(..), buildVDom) as DOM
88
import Halogen.VDom.Machine (Machine, Step(..), extract, step, halt) as Machine
99
import Halogen.VDom.Types (VDom(..), Graft, runGraft, ElemSpec(..), ElemName(..), Namespace(..)) as Types

src/Halogen/VDom/DOM.purs

Lines changed: 134 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
module Halogen.VDom.DOM
2-
( VDomMachine
3-
, VDomStep
4-
, VDomSpec(..)
2+
( VDomSpec(..)
53
, buildVDom
64
, buildText
75
, buildElem
@@ -16,26 +14,32 @@ import Data.Function.Uncurried as Fn
1614
import Data.Maybe (Maybe(..))
1715
import Data.Nullable (toNullable)
1816
import Data.Tuple (Tuple(..), fst)
19-
import Effect (Effect, foreachE)
17+
import Effect (foreachE)
2018
import Effect.Uncurried as EFn
2119
import Halogen.VDom.Machine (Step(..), Machine)
2220
import Halogen.VDom.Machine as Machine
23-
import Halogen.VDom.Types (VDom(..), ElemSpec(..), Namespace(..), runGraft)
21+
import Halogen.VDom.Types (ElemName(..), ElemSpec(..), Namespace(..), VDom(..), runGraft)
2422
import Halogen.VDom.Util as Util
2523
import Web.DOM.Document (Document) as DOM
2624
import Web.DOM.Element (Element) as DOM
2725
import Web.DOM.Element as DOMElement
2826
import Web.DOM.Node (Node) as DOM
2927

30-
type VDomMachine a b = Machine Effect a b
28+
type VDomMachine a w = Machine (VDom a w) DOM.Node
3129

32-
type VDomStep a b = Effect (Step Effect a b)
30+
type VDomStep a w = Step (VDom a w) DOM.Node
31+
32+
type VDomInit i a w = EFn.EffectFn1 i (VDomStep a w)
33+
34+
type VDomBuilder i a w = EFn.EffectFn3 (VDomSpec a w) (VDomMachine a w) i (VDomStep a w)
35+
36+
type VDomBuilder2 i j a w = EFn.EffectFn4 (VDomSpec a w) (VDomMachine a w) i j (VDomStep a w)
3337

3438
-- | Widget machines recursively reference the configured spec to potentially
3539
-- | enable recursive trees of Widgets.
3640
newtype VDomSpec a w = VDomSpec
37-
{ buildWidget VDomSpec a w VDomMachine w DOM.Node
38-
, buildAttributes DOM.Element VDomMachine a Unit
41+
{ buildWidget VDomSpec a w Machine w DOM.Node
42+
, buildAttributes DOM.Element Machine a Unit
3943
, document DOM.Document
4044
}
4145

@@ -48,184 +52,167 @@ newtype VDomSpec a w = VDomSpec
4852
-- | machine3 ← Machine.step machine2 vdomTree3
4953
-- | ...
5054
-- | ````
51-
buildVDom a w. VDomSpec a w VDomMachine (VDom a w) DOM.Node
52-
buildVDom spec = render
55+
buildVDom a w. VDomSpec a w VDomMachine a w
56+
buildVDom spec = build
5357
where
54-
render = case _ of
55-
Text s → buildText spec s
56-
Elem es ch → buildElem spec es ch
57-
Keyed es ch → buildKeyed spec es ch
58-
Widget w → buildWidget spec w
59-
Grafted g → buildVDom spec (runGraft g)
60-
61-
buildText a w. VDomSpec a w String VDomStep (VDom a w) DOM.Node
62-
buildText (VDomSpec spec) = render
58+
build = EFn.mkEffectFn1 case _ of
59+
Text s → EFn.runEffectFn3 buildText spec build s
60+
Elem es ch → EFn.runEffectFn4 buildElem spec build es ch
61+
Keyed es ch → EFn.runEffectFn4 buildKeyed spec build es ch
62+
Widget w → EFn.runEffectFn3 buildWidget spec build w
63+
Grafted g → EFn.runEffectFn1 build (runGraft g)
64+
65+
buildText a w. VDomBuilder String a w
66+
buildText = render
6367
where
64-
render s = do
68+
render = EFn.mkEffectFn3 \(VDomSpec spec) build s → do
6569
node ← EFn.runEffectFn2 Util.createTextNode s spec.document
66-
pure (Step node (Fn.runFn2 patch node s) (done node))
67-
68-
patch = Fn.mkFn2 \node s1 → case _ of
69-
Grafted g →
70-
Fn.runFn2 patch node s1 (runGraft g)
71-
Text s2 → do
72-
let res = Step node (Fn.runFn2 patch node s2) (done node)
73-
case s1 == s2 of
74-
true → pure res
75-
_ → do
76-
EFn.runEffectFn2 Util.setTextContent s2 node
77-
pure res
78-
vdom → do
79-
done node
80-
buildVDom (VDomSpec spec) vdom
70+
let halt = done node
71+
pure (Step node (Fn.runFn4 patch build halt node s) halt)
72+
73+
patch = Fn.mkFn4 \build halt node s1 →
74+
EFn.mkEffectFn1 case _ of
75+
Grafted g →
76+
EFn.runEffectFn1 (Fn.runFn4 patch build halt node s1) (runGraft g)
77+
Text s2 → do
78+
let res = Step node (Fn.runFn4 patch build halt node s2) halt
79+
if s1 == s2
80+
then pure res
81+
else do
82+
EFn.runEffectFn2 Util.setTextContent s2 node
83+
pure res
84+
vdom → do
85+
halt
86+
EFn.runEffectFn1 build vdom
8187

8288
done node = do
83-
parent ← pure (Util.unsafeParent node)
89+
parent ← EFn.runEffectFn1 Util.parentNode node
8490
EFn.runEffectFn2 Util.removeChild node parent
8591

86-
buildElem
87-
a w
88-
. VDomSpec a w
89-
ElemSpec a
90-
Array (VDom a w)
91-
VDomStep (VDom a w) DOM.Node
92-
buildElem (VDomSpec spec) = render
92+
buildElem a w. VDomBuilder2 (ElemSpec a) (Array (VDom a w)) a w
93+
buildElem = render
9394
where
94-
render es1@(ElemSpec ns1 name1 as1) ch1 = do
95+
render = EFn.mkEffectFn4 \(VDomSpec spec) build es1@(ElemSpec ns1 name1 as1) ch1 do
9596
el ← EFn.runEffectFn3 Util.createElement (toNullable ns1) name1 spec.document
9697
let
9798
node = DOMElement.toNode el
9899
onChild = EFn.mkEffectFn2 \ix child → do
99-
res@Step n m h ← buildVDom (VDomSpec spec) child
100+
res@Step n m h ← EFn.runEffectFn1 build child
100101
EFn.runEffectFn3 Util.insertChildIx ix n node
101102
pure res
102103
steps ← EFn.runEffectFn2 Util.forE ch1 onChild
103-
attrs ← spec.buildAttributes el as1
104-
pure
105-
(Step node
106-
(Fn.runFn4 patch node attrs es1 steps)
107-
(Fn.runFn3 done node attrs steps))
108-
109-
patch = Fn.mkFn4 \node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 → case _ of
110-
Grafted g →
111-
Fn.runFn4 patch node attrs es1 ch1 (runGraft g)
112-
Elem es2@(ElemSpec ns2 name2 as2) ch2 | Fn.runFn2 eqElemSpec es1 es2 → do
113-
case Array.length ch1, Array.length ch2 of
114-
0, 0do
115-
attrs' ← Machine.step attrs as2
116-
pure
117-
(Step node
118-
(Fn.runFn4 patch node attrs' es2 ch1)
119-
(Fn.runFn3 done node attrs' ch1))
120-
_, _ → do
121-
let
122-
onThese = EFn.mkEffectFn3 \ix (prev@Step n step halt) vdom → do
123-
res@Step n' m' h' ← step vdom
124-
EFn.runEffectFn3 Util.insertChildIx ix n' node
125-
pure res
126-
onThis = EFn.mkEffectFn2 \ix (Step n _ halt) → halt
127-
onThat = EFn.mkEffectFn2 \ix vdom → do
128-
res@Step n m h ← buildVDom (VDomSpec spec) vdom
129-
EFn.runEffectFn3 Util.insertChildIx ix n node
130-
pure res
131-
steps ← EFn.runEffectFn5 Util.diffWithIxE ch1 ch2 onThese onThis onThat
132-
attrs' ← Machine.step attrs as2
133-
pure
134-
(Step node
135-
(Fn.runFn4 patch node attrs' es2 steps)
136-
(Fn.runFn3 done node attrs' steps))
137-
vdom → do
138-
Fn.runFn3 done node attrs ch1
139-
buildVDom (VDomSpec spec) vdom
104+
attrs ← EFn.runEffectFn1 (spec.buildAttributes el) as1
105+
let halt = Fn.runFn3 done node attrs steps
106+
pure (Step node (Fn.runFn6 patch build halt node attrs es1 steps) halt)
107+
108+
patch = Fn.mkFn6 \build halt node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 →
109+
EFn.mkEffectFn1 case _ of
110+
Grafted g →
111+
EFn.runEffectFn1 (Fn.runFn6 patch build halt node attrs es1 ch1) (runGraft g)
112+
Elem es2@(ElemSpec ns2 name2 as2) ch2 | Fn.runFn2 eqElemSpec es1 es2 → do
113+
case Array.length ch1, Array.length ch2 of
114+
0, 0do
115+
attrs' ← EFn.runEffectFn1 (Machine.step attrs) as2
116+
let halt' = Fn.runFn3 done node attrs' ch1
117+
pure (Step node (Fn.runFn6 patch build halt' node attrs' es2 ch1) halt')
118+
_, _ → do
119+
let
120+
onThese = EFn.mkEffectFn3 \ix prev@(Step _ step _) vdom → do
121+
res@(Step n' _ _) ← EFn.runEffectFn1 step vdom
122+
EFn.runEffectFn3 Util.insertChildIx ix n' node
123+
pure res
124+
onThis = EFn.mkEffectFn2 \ix (Step _ _ h) → h
125+
onThat = EFn.mkEffectFn2 \ix vdom → do
126+
res@(Step n _ _) ← EFn.runEffectFn1 build vdom
127+
EFn.runEffectFn3 Util.insertChildIx ix n node
128+
pure res
129+
steps ← EFn.runEffectFn5 Util.diffWithIxE ch1 ch2 onThese onThis onThat
130+
attrs' ← EFn.runEffectFn1 (Machine.step attrs) as2
131+
let halt' = Fn.runFn3 done node attrs' steps
132+
pure (Step node (Fn.runFn6 patch build halt' node attrs' es2 steps) halt')
133+
vdom → do
134+
halt
135+
EFn.runEffectFn1 build vdom
140136

141137
done = Fn.mkFn3 \node attrs steps → do
142-
parent ← pure (Util.unsafeParent node)
138+
parent ← EFn.runEffectFn1 Util.parentNode node
143139
EFn.runEffectFn2 Util.removeChild node parent
144140
foreachE steps Machine.halt
145141
Machine.halt attrs
146142

147-
buildKeyed
148-
a w
149-
. VDomSpec a w
150-
ElemSpec a
151-
Array (Tuple String (VDom a w))
152-
VDomStep (VDom a w) DOM.Node
153-
buildKeyed (VDomSpec spec) = render
143+
buildKeyed a w. VDomBuilder2 (ElemSpec a) (Array (Tuple String (VDom a w))) a w
144+
buildKeyed = render
154145
where
155-
render es1@(ElemSpec ns1 name1 as1) ch1 = do
146+
render = EFn.mkEffectFn4 \(VDomSpec spec) build es1@(ElemSpec ns1 name1 as1) ch1 do
156147
el ← EFn.runEffectFn3 Util.createElement (toNullable ns1) name1 spec.document
157148
let
158149
node = DOMElement.toNode el
159150
onChild = EFn.mkEffectFn3 \k ix (Tuple _ vdom) → do
160-
res@Step n m hbuildVDom (VDomSpec spec) vdom
151+
res@(Step n _ _)EFn.runEffectFn1 build vdom
161152
EFn.runEffectFn3 Util.insertChildIx ix n node
162153
pure res
163154
steps ← EFn.runEffectFn3 Util.strMapWithIxE ch1 fst onChild
164-
attrs ← spec.buildAttributes el as1
165-
pure
166-
(Step node
167-
(Fn.runFn5 patch node attrs es1 steps (Array.length ch1))
168-
(Fn.runFn3 done node attrs steps))
169-
170-
patch = Fn.mkFn5 \node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 len1 → case _ of
171-
Grafted g →
172-
Fn.runFn5 patch node attrs es1 ch1 len1 (runGraft g)
173-
Keyed es2@(ElemSpec ns2 name2 as2) ch2 | Fn.runFn2 eqElemSpec es1 es2 →
174-
case len1, Array.length ch2 of
175-
0, 0do
176-
attrs' ← Machine.step attrs as2
177-
pure
178-
(Step node
179-
(Fn.runFn5 patch node attrs' es2 ch1 0)
180-
(Fn.runFn3 done node attrs' ch1))
181-
_, len2 → do
182-
let
183-
onThese = EFn.mkEffectFn4 \k ix' (Step n step _) (Tuple _ vdom) → do
184-
res@Step n' m' h' ← step vdom
185-
EFn.runEffectFn3 Util.insertChildIx ix' n' node
186-
pure res
187-
onThis = EFn.mkEffectFn2 \k (Step n _ halt) → halt
188-
onThat = EFn.mkEffectFn3 \k ix (Tuple _ vdom) → do
189-
res@Step n' m' h' ← buildVDom (VDomSpec spec) vdom
190-
EFn.runEffectFn3 Util.insertChildIx ix n' node
191-
pure res
192-
steps ← EFn.runEffectFn6 Util.diffWithKeyAndIxE ch1 ch2 fst onThese onThis onThat
193-
attrs' ← Machine.step attrs as2
194-
pure
195-
(Step node
196-
(Fn.runFn5 patch node attrs' es2 steps len2)
197-
(Fn.runFn3 done node attrs' steps))
198-
vdom → do
199-
Fn.runFn3 done node attrs ch1
200-
buildVDom (VDomSpec spec) vdom
155+
attrs ← EFn.runEffectFn1 (spec.buildAttributes el) as1
156+
let halt = Fn.runFn3 done node attrs steps
157+
pure (Step node (Fn.runFn7 patch build halt node attrs es1 steps (Array.length ch1)) halt)
158+
159+
patch = Fn.mkFn7 \build halt node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 len1 →
160+
EFn.mkEffectFn1 case _ of
161+
Grafted g →
162+
EFn.runEffectFn1 (Fn.runFn7 patch build halt node attrs es1 ch1 len1) (runGraft g)
163+
Keyed es2@(ElemSpec ns2 name2 as2) ch2 | Fn.runFn2 eqElemSpec es1 es2 →
164+
case len1, Array.length ch2 of
165+
0, 0do
166+
attrs' ← EFn.runEffectFn1 (Machine.step attrs) as2
167+
let halt' = Fn.runFn3 done node attrs' ch1
168+
pure (Step node (Fn.runFn7 patch build halt' node attrs' es2 ch1 0) halt')
169+
_, len2 → do
170+
let
171+
onThese = EFn.mkEffectFn4 \_ ix' (Step _ step _) (Tuple _ vdom) → do
172+
res@(Step n' _ _) ← EFn.runEffectFn1 step vdom
173+
EFn.runEffectFn3 Util.insertChildIx ix' n' node
174+
pure res
175+
onThis = EFn.mkEffectFn2 \_ (Step _ _ h) → h
176+
onThat = EFn.mkEffectFn3 \_ ix (Tuple _ vdom) → do
177+
res@(Step n' _ _) ← EFn.runEffectFn1 build vdom
178+
EFn.runEffectFn3 Util.insertChildIx ix n' node
179+
pure res
180+
steps ← EFn.runEffectFn6 Util.diffWithKeyAndIxE ch1 ch2 fst onThese onThis onThat
181+
attrs' ← EFn.runEffectFn1 (Machine.step attrs) as2
182+
let halt' = Fn.runFn3 done node attrs' steps
183+
pure (Step node (Fn.runFn7 patch build halt' node attrs' es2 steps len2) halt')
184+
vdom → do
185+
halt
186+
EFn.runEffectFn1 build vdom
201187

202188
done = Fn.mkFn3 \node attrs steps → do
203-
parent ← pure (Util.unsafeParent node)
189+
parent ← EFn.runEffectFn1 Util.parentNode node
204190
EFn.runEffectFn2 Util.removeChild node parent
205191
EFn.runEffectFn2 Util.forInE steps (EFn.mkEffectFn2 \_ (Step _ _ halt) → halt)
206192
Machine.halt attrs
207193

208-
buildWidget a w. VDomSpec a w w VDomStep (VDom a w) DOM.Node
209-
buildWidget (VDomSpec spec) = render
194+
buildWidget a w. VDomBuilder w a w
195+
buildWidget = render
210196
where
211-
render w = do
212-
res@Step n m h ← spec.buildWidget (VDomSpec spec) w
213-
pure (Step n (patch res) h)
214-
215-
patch prev@(Step node step halt) = case _ of
216-
Grafted g →
217-
patch prev (runGraft g)
218-
Widget w → do
219-
res@Step n m h ← step w
220-
pure (Step n (patch res) h)
221-
vdom → do
222-
halt
223-
buildVDom (VDomSpec spec) vdom
197+
render = EFn.mkEffectFn3 \(VDomSpec spec) build w → do
198+
res@(Step n _ h) ← EFn.runEffectFn1 (spec.buildWidget (VDomSpec spec)) w
199+
pure (Step n (Fn.runFn2 patch build res) h)
200+
201+
patch = Fn.mkFn2 \build prev@(Step node step halt) →
202+
EFn.mkEffectFn1 case _ of
203+
Grafted g →
204+
EFn.runEffectFn1 (Fn.runFn2 patch build prev) (runGraft g)
205+
Widget w → do
206+
res@(Step n _ h) ← EFn.runEffectFn1 step w
207+
pure (Step n (Fn.runFn2 patch build res) h)
208+
vdom → do
209+
halt
210+
EFn.runEffectFn1 build vdom
224211

225212
eqElemSpec a. Fn.Fn2 (ElemSpec a) (ElemSpec a) Boolean
226213
eqElemSpec = Fn.mkFn2 \a b →
227214
case a, b of
228-
ElemSpec ns1 name1 _, ElemSpec ns2 name2 _ | name1 == name2 →
215+
ElemSpec ns1 (ElemName name1) _, ElemSpec ns2 (ElemName name2) _ | name1 == name2 →
229216
case ns1, ns2 of
230217
Just (Namespace ns1'), Just (Namespace ns2') | ns1' == ns2' → true
231218
Nothing, Nothingtrue

0 commit comments

Comments
 (0)