3
votes

I'm looking at some documentation for JS and it's using a string as a makeshift 'enum'. It'd be better to represent this as an algebraic data type, ADT, in my application; however, I'm not really sure what is the best way to turn that ADT into a String on an object for the foreign function interface, FFI, to consume. Given conceptually:

data Foo = Bar | Baz

type Qux = { foo :: Foo }

foreign import quux :: forall e. Qux -> Eff (console :: CONSOLE | e) Unit

main = do
  quux { foo : Bar }

and where qux is { foo : "bar" | "baz" }

exports.quux = function(qux) {
  return function() { 
    console.log(qux)
    //=> Object { foo : "bar" }
  }
}

In Elm I'd use Json.Encode in core to transform the record into a JS object to pass it along, but I'm not sure of the analog in PureScript.

1

1 Answers

3
votes

I would do something like this:

data Foo = Bar | Baz

printFoo :: Foo -> String
printFoo = case _ of
  Bar -> "bar"
  Baz -> "baz"

type Qux = { foo :: Foo }

foreign import _quux :: forall e. { foo :: String } -> Eff (console :: CONSOLE | e) Unit

quux :: forall e. Qux -> Eff (console :: CONSOLE | e) Unit
quux args = _quux { foo: printFoo args.foo }

main = do
  quux { foo : Bar }

The idea being you adapt the arguments for the FFI function _quux with quux, and then avoid exporting _quux from the module, so only the "safe" interface is accessible.

Another advantage of this approach is you could give the quux function a more PS-friendly argument setup, as passing records as options is not generally the norm, unless the function is going to accept a lot of stuff:

quux :: forall e. Foo -> Eff (console :: CONSOLE | e) Unit
quux foo = _quux { foo: printFoo foo }

main = do
  quux Bar

Basically what I'm suggesting is that whenever you're using the FFI you want to do as little work as possible in the FFI, and handle as much of the implementation as you can in PS. That way more of the code you write is still checkable by the compiler, and you don't have to do anything clever in the JS or write things that may break if PS's implementation details change in some future version.