0

If I have this SML datatype

datatype json =
         Num of real
       | String of string
       | False
       | True
       | Null
       | Array of json list
       | Object of (string * json) list

Let's say I have this Array with only one Object which makes it a json list

Array[Object[("a", Num (1.0)),("b", True)]]

how can I cons a new Object onto this existing Array? I've tried a simple :: to no avail

Object[("a", Num (1.0)),("b", True)]::Array[Object[("a", Num (2.0)),("b", True)]]

which gives an error. Do I have to build my own cons for this? It seems the SML list is 'a list which should allow json list and work with ::

Yes, this is a homework assignment from a past semester of Programming Languages at the U. of Washington that I'm doing on my own. This is the assignment.

My basic problem is I don't know how to add to an Array with recursion calls. If I need to generate an Array containing Objects and add a new Object to that starting Array with each recursion call, how would that be done? I've seen examples of Succ or Cons, e.g., a successor constructor, but those just create a recursive, nested object such as

val four = Succ (Succ (Succ (Succ Zero)))

...but this isn't helpful...

0

3 Answers 3

1

Array [...] is no a json list, it's a json, and :: can't cons two jsons into a list.

You need to cons onto the list "inside" the Array:

Array (Object [("a", Num 1.0)] :: ([Object [("a", Num 2.0)]]))

You probably want to add a "cons for JSON" function; something like

fun json_cons o (Array os) = Array (o :: os)
  | json_cons _ _ = ... handle structural error ...

You can also invent your own binary infix operator, but that's probably a bit on the advanced side for this assignment.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, this got me going again. However, the fact that ([Object [("a", Num 2.0)]]) is a json list like [2] is 'a list is rather bizarre looking, and I would have been in many "guess-test" cycles.
[2] is an int list, not an 'a list (you can't create an 'a list, since they can't exist); 2 is an int, and adding the [] around it makes an int list. If an expression e has the type json, [e] has the type json list.
Good, but why are the parentheses necessary around [Object [("a", Num 2.0)]] for list consing? If [2] is an int list, why isn't just [Object [("a", Num 2.0)]] a json list ready for consing? Instead, I need ([Object [("a", Num 2.0)]]) to do consing.
Ok, you got me there... The parentheses are actually not necessary, due to the low precedence of ::. I put them there for clarity, but Array (Object [("a", Num 1.0)] :: [Object [("a", Num 2.0)]]) also works.
0

With molbdnilo's help, I got past the mental block of how to create an Array list. Since Array is also a constructor, i.e., like a function, we can do things inside this constructor function call, namely, we can do a normal list cons inside the Array constructor

fun json_cons (ob, (Array os)) = Array (ob::os)
  | json_cons (_,_) = (Array [])

Testing

- json_cons (Object[("a", Num (1.0)),("b", True)], Array[])
val it = Array [Object [(#,#),(#,#)]] : json

Here's an another example at directly constructing

- Array (Object [("a", Num 1.0)] :: ([Object [("a", Num 2.0)]]))
val it = Array [Object [(#,#)],Object [(#,#)]] : json

For someone used to 1::[2] this is bizarre, especially the ([Object[...]]) as the cdr part. So here is the code

fun make_silly_json (i) =
    case i of
        0 => Array [Object []]
      | x => json_cons (Object [("n", Num (Real.fromInt (x))),("b", True)], make_silly_json (x-1))

Testing

make_silly_json 3
    val it = Array [Object [(#,#),(#,#)],Object [(#,#),(#,#)],Object [(#,#),(#,#)],Object []] : json

...types...

Comments

0

Thank for molbdnilo's help on creating the "cons for JSON" function. Attaching a tail recursion version of the solution:

fun make_silly_json i =
    let fun aux(i, acc) =
        if i = 0
        then acc
        else let val json_val = Object[("n", Num(int_to_real(i))),("b", True)]
                 fun json_con (obj, (Array os)) =
                    Array(obj::os)
                  | json_con (_,_) = (Array [])
             in
                aux(i-1, json_con(json_val, acc))
             end
    in aux(i, Array[])
    end

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.