我正在查看JS的一些文档,它使用字符串作为临时的“枚举”.在我的应用程序中最好将其表示为代数数据类型ADT.但是,我不确定如何将ADT转换为对象上供外部函数接口FFI使用的String的最佳方法.从概念上讲:
data Foo = Bar | Baz
type Qux = { foo :: Foo }
foreign import quux :: forall e. Qux -> Eff (console :: CONSOLE | e) Unit
main = do
quux { foo : Bar }
qux是{foo:“ bar” | “巴兹”}
exports.quux = function(qux) {
return function() {
console.log(qux)
//=> Object { foo : "bar" }
}
}
在Elm中,我会在核心中使用Json.Encode将记录转换为JS对象以将其传递,但是我不确定PureScript中的模拟.
解决方法:
我会做这样的事情:
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 }
您的想法是使用quux修改FFI函数_quux的参数,然后避免从模块中导出_quux,因此只能访问“安全”接口.
这种方法的另一个优点是,您可以为quux函数提供一个更加PS友好的参数设置,因为将记录作为选项传递通常不是常态,除非该函数将接受很多东西:
quux :: forall e. Foo -> Eff (console :: CONSOLE | e) Unit
quux foo = _quux { foo: printFoo foo }
main = do
quux Bar
基本上,我的建议是,无论何时使用FFI,您都希望在FFI中做尽可能少的工作,并在PS中处理尽可能多的实现.这样,您编写的更多代码仍可以由编译器检查,并且您不必在JS中做任何聪明的事情,也不必编写可能会在PS的实现详细信息在将来的版本中更改的情况下中断的事情.