[Ur] Polymorphic variants and JSON

Edward Z. Yang ezyang at MIT.EDU
Sat Apr 14 19:29:32 EDT 2012


OK, this one is being fiddly:

   val (r, s') = @foldR2 [json] [fn _ => string] [fn ts => variant ts * string]
                  (fn [nm ::_] [t ::_] [rest ::_] [[nm] ~ rest] (j : json t) name' acc =>
                      if name = name' then
                          let
                              val (v, s') = j.FromJson s'
                          in
                              (make [nm] v, s')
                          end
                      else
                          let
                              val (v, s') = acc
                          in
                              (Variant.weaken v, s')
                          end)
                  (error <xml>Unknown JSON object field name {[name]}</xml>)
                  fl jss names

(Never mind the fact that this will always result in an error, I'm planning on fixing
that later).

This particular permutation gives me:

    /home/ezyang/Dev/logitext/meta/json.ur:300:55-300:69: Can't resolve type class instance
    Class constraint:  Top.folder[[Type]] rest

and I don't know how to spell the implicit arguments correctly or what
folder I should be giving it (it's /almost/ 'fl' except that the
entries in front need to be lopped off).  Is there a version of fold which
also gives me folders?

I've also tried holding the type of the variant to be 'ts' through the entire
fold, but then Urweb isn't smart enough to unify:

    Can't unify record constructors
       Have: 
    [#1 = Basis.variant (([nm = t]) ++ <UNIF:U1173::{Type}>), 
      #2 = Basis.string]
       Need:  [#1 = Basis.variant ts, #2 = Basis.string]
      Field:  #1
    Value 1:  Basis.variant (([nm = t]) ++ <UNIF:U1173::{Type}>)
    Value 2:  Basis.variant ts
    Can't unify record constructors
    Have:  <UNIF:U1173::{Type}> ++ [nm = t]
    Need:  ts

Edward

Excerpts from Adam Chlipala's message of Sat Apr 14 18:23:19 -0400 2012:
> Edward Z. Yang wrote:
> > (And even that's not enough, since something like $(map json ts) 
> > counts as a typeclass witness too--so what is a witness, anyway?)
> 
> Yes, records built by mapping over type classes are also witnesses. :)
> 
> > Yeah, here is the ambiguity thing, since there exists a destr2R but
> > it doesn't have the right signature here.
> >
> > map2 is useful.  With it, I get here:
> >
> >      {ToJson = fn r =>  let val jsts = @map2 [json] [fn _ =>  string] [fn x =>  json x * string]
> >                                       (fn [t] (js : json t) (t : string) =>  (js, t)) fl jss names
> >                        in @Variant.destrR [ident] [fn x =>  json x * string]
> >                            (fn [p] (v : p) (js : json p, t : string) =>  "something") fl r jsts
> >                        end
> >
> > I can't get this to unify:
> >
> >      /home/ezyang/Dev/logitext/meta/json.ur:273:26-273:83: Unification failure
> >      Expression:
> >      fn p ::: Type =>
> >       fn v : p =>
> >        fn $x : {1 : json p, 2 : string} =>
> >         case $x of {1 = js, 2 = t} =>  "something"
> >        Have con:
> >      p ::: Type ->
> >       (p ->
> >         ({1 :
> >            {ToJson : (p ->  string),
> >              FromJson : (string ->  {1 : p, 2 : string})}, 2 : Basis.string}
> >           ->  Basis.string))
> >        Need con:
> >      p :: Type ->
> >       (p ->
> >         ({1 :
> >            {ToJson : (p ->  string),
> >              FromJson : (string ->  {1 : p, 2 : string})}, 2 : Basis.string}
> >           ->  <UNIF:U1048::Type+1>))
> >      Differing constructor function explicitness
> >      Have:
> >      p ::: Type ->
> >       (p ->
> >         ({1 :
> >            {ToJson : (p ->  string),
> >              FromJson : (string ->  {1 : p, 2 : string})}, 2 : Basis.string}
> >           ->  Basis.string))
> >      Need:
> >      p :: Type ->
> >       (p ->
> >         ({1 :
> >            {ToJson : (p ->  string),
> >              FromJson : (string ->  {1 : p, 2 : string})}, 2 : Basis.string}
> >           ->  <UNIF:U1048::Type+1>))
> 
> I think this error message is actually pretty good!  In the expression 
> quoted, you need to change the binder of [p] to mark it as explicit, not 
> implicit.  The easy way to do that is to change [[p]] to [[p ::_]] (note 
> no space between [::] and [_]).



More information about the Ur mailing list