我目前正在试验 ghcjs 中的JSaddle库。
我还没有太多的镜头经验。在这个库的某个地方,他们似乎定义了一个 getter lens,它实际上是一种 monadic setter:
-- | 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 抱怨说含蓄的多态性......