@@ -11,19 +11,11 @@ module Ur.Deconstructor exposing
1111
1212{-| This module provides an API to deconstruct `Noun`s into arbitrary Elm data structures.
1313
14−The principal (and types) are very similar to `Url.Parser` from `elm/url`.
15−
1614You would parse a `[%edit @ cord]` like this:
1715
1816 type alias Edit = {id: Int, text : String}
1917
20− (D.cell (D.const D.cord "edit") (D.cell D.int D.cord)) |> D.map Edit
21−
22−When you `map` a `Deconstructor` the function you pass to `map` will accept exactly the number of arguments
23−that "captured" values in exacly the order they occured in the `Deconstructor`.
24−
25−In our case we `map` the `Edit` type, which accepts exaclty two arguments because there are two `Deconstructor`s
26−that "capture" a value: `D.int` and `D.cord`.
18+ (D.cell (D.const D.cord "edit") (D.cell D.bigint D.cord)) |> D.map (\( (), ( id, txt ) ) -> Edit id txt)
2719
2820@docs Deconstructor
2921
@@ -80,27 +72,25 @@ import Ur.Types exposing (..)
8072
8173{-| A `Noun` deconstructor.
8274-}
83−type Deconstructor a b
84− = Deconstructor (Noun -> a -> Maybe b)
75+type alias Deconstructor a =
76+ Noun -> Maybe a
8577
8678
8779{-| Executes a `Deconstructor` on a `Noun`.
8880-}
89−run : Deconstructor (a -> a) a -> Noun -> Maybe a
90−run (Deconstructor f) noun =
91− f noun identity
81+run : Deconstructor a -> Noun -> Maybe a
82+run f noun =
83+ f noun
9284
9385
9486{-| Executes a deconstructor on a `jam`med `Noun`.
9587-}
96−runBytes : Deconstructor (a -> a) a -> Bytes -> Maybe a
97−runBytes (Deconstructor f) bs =
98− cue bs
99− |> Maybe.andThen
100− (\noun -> f noun identity)
88+runBytes : Deconstructor a -> Bytes -> Maybe a
89+runBytes f bs =
90+ cue bs |> Maybe.andThen f
10191
10292
103−{-| Asserts that the value at the current position should be exactly equal to the second argument.
93+{-| Asserts that the value should be exactly equal to the second argument.
10494
10595The first argument is a `Deconstructor` for the given type.
10696
@@ -109,104 +99,39 @@ The second argument is the value to compare with.
10999This is useful to match on `term`s when there are multiple possible cases in a head-tagged union.
110100
111101-}
112−const : Deconstructor (a -> a) a -> a -> Deconstructor c c
113−const (Deconstructor f) value =
114− Deconstructor
115− (\noun c ->
116− case f noun identity of
117− Just a ->
118− if a == value then
119− Just c
120−
121− else
122− Nothing
123−
124− Nothing ->
125− Nothing
126− )
102+const : Deconstructor a -> a -> Deconstructor ()
103+const f value noun =
104+ case f noun of
105+ Just a ->
106+ if a == value then
107+ Just ()
127108
109+ else
110+ Nothing
128111
129−{-| Extracts a `cord` at the current location.
130−-}
131−cord : Deconstructor (String -> a) a
132−cord =
133− Deconstructor
134− (\x f ->
135− case x of
136− Atom bs ->
137− BD.decode (BD.string (Bytes.width bs)) bs
138− |> Maybe.map f
139−
140− Cell _ ->
141− Nothing
142− )
143−
112+ Nothing ->
113+ Nothing
144114
145−{-| Extracts a `tape` at the current location.
146−-}
147−tape : Deconstructor (String -> a) a
148−tape =
149− list cord |> fmap String.concat
150115
116+bigint : Deconstructor BigInt
117+bigint x =
118+ case x of
119+ Atom bs ->
120+ BigInt.Bytes.decode bs |> Just
151121
152−{-| Extracts a 32-bit unsigned `Int` at the given location.
153−
154−If the `Atom` at the current location is larger than 32 bits the the behaviour is undefined.
155−
156−-}
157−int : Deconstructor (Int -> a) a
158−int =
159− Deconstructor
160− (\x f ->
161− case x of
162− Atom bs ->
163− (case Bytes.width bs of
164− 1 ->
165− BD.decode BD.unsignedInt8 bs
166−
167− 2 ->
168− BD.decode (BD.unsignedInt16 LE) bs
169−
170− 3 ->
171− BD.decode (BD.unsignedInt32 LE) (BE.encode (BE.sequence [ BE.bytes bs, BE.unsignedInt8 0 ]))
172−
173− 4 ->
174− BD.decode (BD.unsignedInt32 LE) bs
175−
176− _ ->
177− Nothing
178− )
179− |> Maybe.map f
180−
181− Cell _ ->
182− Nothing
183− )
184−
185−
186−{-| Extracts a `BigInt` at the current location.
187−-}
188−bigint : Deconstructor (BigInt -> a) a
189−bigint =
190− Deconstructor
191− (\x f ->
192− case x of
193− Atom bs ->
194− BigInt.Bytes.decode bs |> f |> Just
195−
196− Cell _ ->
197− Nothing
198− )
122+ Cell _ ->
123+ Nothing
199124
200125
201−{-| Extracts a 32-bit signed `Int` at the given location.
126+{-| Extracts a 32-bit signed `Int`.
202127
203−If the `Atom` at the current location is larger than 32 bits the the behaviour is undefined.
128+If the `Atom` is larger than 32 bits the the behaviour is undefined.
204129
205130-}
206−signedInt : Deconstructor (Int -> a) a
131+signedInt : Deconstructor Int
207132signedInt =
208133 int
209− |> fmap
134+ |> map
210135 (\i ->
211136 if Bitwise.and 1 i == 1 then
212137 -(Bitwise.shiftRightBy 1 (1 + i))
@@ -216,105 +141,85 @@ signedInt =
216141 )
217142
218143
219−{-| Extracts a 32-bit `Float` at the given location.
144+{-| Extracts a 32-bit `Float`.
220145-}
221−float32 : Deconstructor (Float -> a) a
222−float32 =
223− Deconstructor
224− (\x f ->
225− case x of
226− Atom bs ->
227− BD.decode (BD.float32 LE) bs
228− |> Maybe.map f
229−
230− Cell _ ->
231− Nothing
232− )
146+float32 : Deconstructor Float
147+float32 x =
148+ case x of
149+ Atom bs ->
150+ BD.decode (BD.float32 LE) bs
151+
152+ Cell _ ->
153+ Nothing
233154
234155
235−{-| Extracts a 64-bit `Float` at the given location.
156+{-| Extracts a 64-bit `Float`.
236157-}
237−float64 : Deconstructor (Float -> a) a
238−float64 =
239− Deconstructor
240− (\x f ->
241− case x of
242− Atom bs ->
243− BD.decode (BD.float64 LE) bs
244− |> Maybe.map f
245−
246− Cell _ ->
247− Nothing
248− )
158+float64 : Deconstructor Float
159+float64 x =
160+ case x of
161+ Atom bs ->
162+ BD.decode (BD.float64 LE) bs
163+
164+ Cell _ ->
165+ Nothing
249166
250167
251−{-| Extracts the raw `Byte`s of an `Atom` at the current location.
168+{-| Extracts the raw `Byte`s of an `Atom`.
252169-}
253−bytes : Deconstructor (Bytes -> a) a
254−bytes =
255− Deconstructor
256− (\n f ->
257− case n of
258− Atom bs ->
259− f bs |> Just
260−
261− Cell _ ->
262− Nothing
263− )
170+bytes : Deconstructor Bytes
171+bytes n =
172+ case n of
173+ Atom bs ->
174+ Just bs
175+
176+ Cell _ ->
177+ Nothing
264178
265179
266−{-| Asserts the the `Atom` at the current position should be exactly `sig` (`~`).
180+{-| Asserts the the `Atom` should be exactly `sig` (`~`).
267181-}
268−sig : Deconstructor a a
269−sig =
270− Deconstructor
271− (\n a ->
272− case n of
273− Atom b ->
274− if (Bytes.Extra.toByteValues b |> List.filter (\x -> x /= 0)) == [] then
275− Just a
276−
277− else
278− Nothing
279−
280− Cell _ ->
281− Nothing
282− )
182+sig : Deconstructor ()
183+sig n =
184+ case n of
185+ Atom b ->
186+ if (Bytes.Extra.toByteValues b |> List.filter (\x -> x /= 0)) == [] then
187+ Just ()
188+
189+ else
190+ Nothing
283191
192+ Cell _ ->
193+ Nothing
284194
285−{-| Extracts a sig-terminated list of arbitrary elements at the current position.
195+
196+{-| Extracts a sig-terminated list of arbitrary elements.
286197
287198The first argument is a `Deconstructor` of the elements of the list.
288199
289200-}
290−list : Deconstructor (a -> a) a -> Deconstructor (List a -> b) b
291−list (Deconstructor f) =
292− Deconstructor
293− (\n g ->
294− let
295− go n_ =
296− case n_ of
297− Atom _ ->
298− Just []
299−
300− Cell ( el, tail ) ->
301− Maybe.map2 (\a b -> a :: b) (f el identity) (go tail)
302− in
303− go n |> Maybe.map g
304− )
305−
306−
307−alt : Deconstructor a b -> Deconstructor a b -> Deconstructor a b
308−alt (Deconstructor f) (Deconstructor g) =
309− Deconstructor
310− (\n a ->
311− case f n a of
312− Just x ->
313− Just x
314−
315− Nothing ->
316− g n a
317− )
201+list : Deconstructor a -> Deconstructor (List a)
202+list f n =
203+ let
204+ go n_ =
205+ case n_ of
206+ Atom _ ->
207+ Just []
208+
209+ Cell ( el, tail ) ->
210+ Maybe.map2 (\a b -> a :: b) (f el) (go tail)
211+ in
212+ go n
213+
214+
215+alt : Deconstructor a -> Deconstructor a -> Deconstructor a
216+alt f g n =
217+ case f n of
218+ Just x ->
219+ Just x
220+
221+ Nothing ->
222+ g n
318223
319224
320225{-| Try to execute all of the `Deconstructor`s in order until one succeeds.
@@ -322,77 +227,109 @@ alt (Deconstructor f) (Deconstructor g) =
322227This is especially useful for deconstructing head-tagged unions from Hoon.
323228
324229-}
325−oneOf : List (Deconstructor a b) -> Deconstructor a b
230+oneOf : List (Deconstructor a) -> Deconstructor a
326231oneOf l =
327232 case l of
328233 [] ->
329− Deconstructor (\_ _ -> Nothing)
234+ always Nothing
330235
331236 x :: xs ->
332237 alt x (oneOf xs)
333238
334239
335−{-| Extract the raw `Noun` at the current position.
240+{-| Ignore any value.
336241
337−Always succeeds.
242+This is useful when you have a value you don't care about. `ignore` allows you to just skip the value.
338243
339244-}
340−tar : Deconstructor (Noun -> a) a
341−tar =
342− Deconstructor (\noun f -> Just (f noun))
245+ignore : Deconstructor ()
246+ignore =
247+ always (Just ())
343248
344249
345−{-| Ignore any value at the current position.
250+{-| Extracts a [`Cell`](https://developers.urbit.org/reference/glossary/cell) (pair) of two arbitrary values.
346251
347−This is useful when you have a value you don't care about. `ignore` allows you to just skip the value.
252+Accepts two arbitrary `Deconstructor`s that form a Cell.
348253
349254-}
350−ignore : Deconstructor a a
351−ignore =
352− Deconstructor (\_ f -> Just f)
255+cell : Deconstructor a -> Deconstructor b -> Deconstructor ( a, b )
256+cell l r noun =
257+ case noun of
258+ Cell ( lhs, rhs ) ->
259+ l lhs |> Maybe.andThen (\a -> r rhs |> Maybe.map (\b -> ( a, b )))
353260
261+ Atom _ ->
262+ Nothing
354263
355−{-| Extracts a [`Cell`](https://developers.urbit.org/reference/glossary/cell) (pair) of two arbitrary values.
356264
357−Accepts two arbitrary `Deconstructor`s that form a Cell.
265+{-| Maps (applies) a function to all of the values deconstructed.
266+
267+This is useful when you want to create a data type with extracted values as fields.
358268
359269-}
360−cell : Deconstructor a b -> Deconstructor b c -> Deconstructor a c
361−cell (Deconstructor l) (Deconstructor r) =
362− Deconstructor
363− (\noun a ->
364− case noun of
365− Cell ( lhs, rhs ) ->
366− l lhs a |> Maybe.andThen (\b -> r rhs b)
270+lazy : (() -> Deconstructor a) -> Deconstructor a
271+lazy f noun =
272+ f () noun
367273
368− Atom _ ->
369− Nothing
370− )
274+
275+map : (a -> b) -> Deconstructor a -> Deconstructor b
276+map g f noun =
277+ f noun |> Maybe.map g
371278
372279
373−{-| "Lazily" applies a deconstructor.
374−This is useful when you are defining a recursive `Deconstructor` which needs to call itself.
280+{-| Extracts a `cord`.
375281-}
376−lazy : (() -> Deconstructor a b) -> Deconstructor a b
377−lazy f =
378− Deconstructor
379− (\noun a ->
380− case f () of
381− Deconstructor g ->
382− g noun a
383− )
282+cord : Deconstructor String
283+cord x =
284+ case x of
285+ Atom bs ->
286+ BD.decode (BD.string (Bytes.width bs)) bs
384287
288+ Cell _ ->
289+ Nothing
385290
386−{-| Maps (applies) a function to all of the values deconstructed.
387291
388−This is useful when you want to create a data type with extracted values as fields.
292+{-| Extracts a `tape`.
293+-}
294+tape : Deconstructor String
295+tape =
296+ list cord |> map String.concat
297+
298+
299+{-| Extracts a 32-bit unsigned `Int`.
300+
301+If the `Atom` is larger than 32 bits the the behaviour is undefined.
389302
390303-}
391−map : a -> Deconstructor a b -> Deconstructor (b -> c) c
392−map a (Deconstructor f) =
393− Deconstructor (\noun g -> f noun a |> Maybe.map g)
304+int : Deconstructor Int
305+int x =
306+ case x of
307+ Atom bs ->
308+ case Bytes.width bs of
309+ 1 ->
310+ BD.decode BD.unsignedInt8 bs
311+
312+ 2 ->
313+ BD.decode (BD.unsignedInt16 LE) bs
314+
315+ 3 ->
316+ BD.decode (BD.unsignedInt32 LE) (BE.encode (BE.sequence [ BE.bytes bs, BE.unsignedInt8 0 ]))
317+
318+ 4 ->
319+ BD.decode (BD.unsignedInt32 LE) bs
394320
321+ _ ->
322+ Nothing
323+
324+ Cell _ ->
325+ Nothing
326+
327+
328+{-| Extract the raw `Noun`.
395329
396−fmap : (a -> b) -> Deconstructor (a -> c) c -> Deconstructor (b -> c) c
397−fmap f (Deconstructor g) =
398− Deconstructor (\noun h -> g noun (f >> h))
330+Always succeeds.
331+
332+-}
333+tar : Deconstructor Noun
334+tar =
335+ Just