Sequencing monadic actions where every action takes the original input

107 Views Asked by At

I'm currently experimenting with the JSaddle library in ghcjs.

I don't have much of any experience with lenses yet. Somewhere in this library they seem to define a getter lens which is actually a sort of 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)

Using this in the following manner to set properties on a new javascript object works:

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

But I'd like to drop the cruft and have something like this:

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

I know you can do this in the lens library like this because the setters actually return the updated object:

obj & _1 .~ 45
    & _2 .~ 49

Right now I made a small shim function that returns the input value every time:

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

This allows me to use jss the way I'd like to:

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

But I can't help but feel that I'm trying to fix a solved problem. Is there a better way I don't know about?

[EDIT]

I did try something like this:

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

But then GHCJS complains about impredicative polymorphism...

0

There are 0 best solutions below