1

我目前正在试验 ghcjs 中的JSaddle库。

我还没有太多的镜头经验。在这个库的某个地方,他们似乎定义了一个 getter lens,它实际上是一种 monadic setter:

https://github.com/ghcjs/jsaddle/blob/3f8b32833917f1a2dfbdb81ef00992fb54733c9a/jsaddle/src/Language/Javascript/JSaddle/Object.hs#L201

-- | Makes a setter for a particular property name.
--
-- > jss name = to (<#name)
--
-- >>> testJSaddle $ eval "'Hello World'.length = 12"
-- 12
-- >>> testJSaddle $ val "Hello World" ^. jss "length" 12
-- undefined
jss :: (ToJSString name, ToJSVal val)
   => name          -- ^ Name of the property to find
   -> val
   -> forall o . MakeObject o => IndexPreservingGetter o (JSM ())
jss name val = to (\o -> o <# name $ val)

以下列方式使用它在新的 javascript 对象上设置属性有效:

makeConfig :: JSM Object
makeConfig = do
    object <- obj
    object ^. jss "foo" 5
    object ^. jss "bar" 7
    return object

但我想放弃杂物并有这样的东西:

makeConfig :: JSM Object
makeConfig = obj ^. jss "foo" 5
                 ^. jss "bar" 7

我知道您可以lens像这样在库中执行此操作,因为设置器实际上返回了更新的对象:

obj & _1 .~ 45
    & _2 .~ 49

现在我做了一个小垫片函数,每次都返回输入值:

(~.) :: MakeObject o => o -> IndexPreservingGetter o (JS.JSM ()) -> JS.JSM o
a ~. b = a ^. b >> return a

这使我可以使用jss我想要的方式:

makeConfig :: JSM Object
makeConfig = obj ~. jss "foo" 5
                 ~. jss "bar" 7

但我不禁觉得我正在尝试解决一个已解决的问题。有没有更好的方法我不知道?

[编辑]

我确实尝试过这样的事情:

props :: MakeObject o => o -> [IndexPreservingGetter o (JS.JSM ())] -> JS.JSM o
props object p = mapM_ (object ^.) p >> return object

但随后 GHCJS 抱怨说含蓄的多态性......

4

0 回答 0