agson
Version:
Querying and manipulating JSON graphs
109 lines (91 loc) • 2.46 kB
text/coffeescript
{Just, Nothing, fromNullable, fromValidation} = require 'data.maybe'
lens = require('./Lens').of
{identity} = require './lenses'
# (ma -> boolean) -> Lens a b
where = (predm) -> lens "where(#{predm.toString()})", (ma) ->
modify: (f) ->
unless predm(ma)
ma
else
f ma
get: ->
unless predm(ma)
Nothing()
else
ma
lensListAsString = (list) -> (abl.toString() for abl in list).join ','
lensMapAsString = (object) -> ("#{key}:#{abl.toString()}" for key, abl of object).join ','
product = do ->
tuple: (list) -> lens "product.tuple[#{lensListAsString list}]", (ma) ->
get: ->
tuple = Just []
for abl in list
tuple = tuple.chain (t) ->
abl.runM(ma).get().chain (b) ->
t.push b
Just t
tuple
modify: (f) ->
f().chain (tuple) ->
result = ma
for abl in list
result = result.chain ->
mb = fromNullable(tuple.shift())
abl.runM(result).modify -> mb
result
dict: (object) -> lens "product.dict{#{lensMapAsString object}}", (ma) ->
get: ->
dict = Just {}
for key, abl of object
dict = dict.chain (d) ->
abl.runM(ma).get().chain (b) ->
d[key] = b
Just d
dict
modify: (f) ->
f().chain (dict) ->
result = ma
for key, abl of object
result = result.chain ->
mb = fromNullable dict[key]
abl.runM(result).modify -> mb
result
fromValidator = (validator) -> lens "validate", (ma) ->
get: ->
ma.chain (a) ->
fromValidation validator a
modify: (f) ->
ma.chain (a) ->
validb = fromValidation(validator a)
if validb.isJust
f validb
else
ma
sum = do ->
withTag = (tag, value) ->
tagged = {}
tagged[tag] = value
Just tagged
tagged: (tagsToLenses) -> lens "sum.tagged(#{lensMapAsString tagsToLenses})", (ma) ->
get: ->
result = Nothing()
for tag, abl of tagsToLenses
mb = abl.runM(ma).get()
if mb.isJust
result = withTag tag, mb.get()
break
result
modify: (f) ->
result = Nothing()
for tag, abl of tagsToLenses
tagged = abl.runM(ma).get()
if tagged.isJust
result = f withTag tag, tagged.get()
break
result
module.exports = {
where
product
fromValidator
sum
}