mikeplus64 / aeson-flowtyped

Moved to https://gitlab.com/transportengineering/aeson-flowtyped
BSD 3-Clause "New" or "Revised" License
6 stars 2 forks source link

Polymorphism tests are broken #1

Open mgsloan opened 6 years ago

mgsloan commented 6 years ago
  nullable:                                           OK
  array:                                              OK
  User export:                                        OK
  Recursive type export:                              OK
  Nullary string tags (2 tags):                       OK
  Nullary string tags (3 tags):                       OK
  Nullary string tags (4 tags):                       OK
  map-style object / hashmap instance:                OK
  parens around nullable array:                       OK
  parens around nullable array of nullable elements:  OK
  export dependencies:                                OK
  polymorphism (arity 1):                             OK
  polymorphism (arity 2):                             FAIL
    expected: "// @flow\n// This module has been generated by aeson-flowtyped.\n\nexport type Poly2<A, B> =\n  {| tag: 'Poly2', contents: [A,B] |} |\n  {| tag: 'Poly2Go', contents: Poly2<A, B> |};\n"
     but got: "// @flow\n// This module has been generated by aeson-flowtyped.\n\nexport type Poly2<B, A> =\n  {| tag: 'Poly2', contents: [A,B] |} |\n  {| tag: 'Poly2Go', contents: Poly2<A, B> |};\n"
  monomorphic use of polymorphic type (dependencies): OK
  monomorphic use of polymorphic type:                FAIL
    expected: "// @flow\n// This module has been generated by aeson-flowtyped.\n\nexport type Poly2<A, B> =\n  {| tag: 'Poly2', contents: [A,B] |} |\n  {| tag: 'Poly2Go', contents: Poly2<A, B> |};\n"
     but got: "// @flow\n// This module has been generated by aeson-flowtyped.\n\nexport type Mono<A, B> =\n  {| tag: 'Mono', contents: [Poly2<A, B>,Poly2<B, A>] |};\nexport type Poly2<A, B> =\n  {| tag: 'Poly2', contents: [number,boolean] |} |\n  {| tag: 'Poly2Go', contents: Poly2<A, B> |};\n"

2 out of 15 tests failed (0.00s)                                                                                                                                                                                                                  
aeson-flowtyped-0.9.1: Test suite aeson-flowtyped failed
Completed 2 action(s).             
Test suite failure for package aeson-flowtyped-0.9.1
    aeson-flowtyped:  exited with: ExitFailure 1
Logs printed to console

Looks like what's happening is:

  1. Usages of polymorphic types use the variables instead of the arguments.
  2. The type variables in the exported type seem to be determined by the usages of type variables within the definition. Moreover, they are stored in a hashmap so they come out in arbitrary order. Instead, the order of the variables from the haskell definition should be used.
mgsloan commented 6 years ago

I've looked at this a bit more and it appears to be a limitation of generics. Not sure though, maybe there's a way around it.

mikeplus64 commented 6 years ago

I think you're basically right with the diagnosis.

By the power of closed type families, undecidable instances, and polykinds, I've made the following evil incantations that might work to get the type arguments of an arbitrary type:

data Wrap a -- poly-kinded wrapper

type family Vars' f xs where
  Vars' (Wrap (f x)) xs = Vars' (Wrap f) (x:xs)
  Vars' z xs            = xs

type Vars a = Vars' (Wrap a) '[]

From that we should be able to derive flowTypeVars, which should also be being used in the pretty-printer directly, instead of the weird map-building stuff it does now.