Such sorrow.
var _ = ramda
var nestedObj = {
level1: {
hello: 'Deepworld'
},
hello: 'shallowworld'
}
var operation = function (string) {
return string + ' SUCCESS!!!'
}
var result = ramda.map(operation, nestedObj)
console.log(result)
> {"level1":"[object Object] SUCCESS!!!","hello":"shallowworld SUCCESS!!!"}
i don't know why you would assume map would recursively descend. i don't see any reason to "fix" this, 'cuz it doesn't look like a problem to me.
just saying.
Let's take a step back to consider the type of map:
Functor f => (a -> b) -> f a -> f b
{level1: {hello: 'Deepworld'}, hello: 'shallowworld'} is incompatible with this function since we cannot resolve a in f a. If f is StrMap we have
{hello: 'Deepworld'} :: StrMap a, { hello :: String }
and
'shallowworld' :: String
as a values, and there is no _standard_ type of which all a values are members.
We could, though, define a recursive string map type: a data type mapping strings to values of a certain type _or_ to recursive string maps of that same type.
Every value of type StrMap a would also be a member of RecStrMap a. For example:
{CA: true, NY: false} :: StrMap Boolean, RecStrMap Boolean
But unlike the StrMap type, the RecStrMap type would support arbitrary nesting:
{R: {a: {m: {d: {a: true}}}}, S: {a: {n: {c: {t: {u: {a: {r: {y: false}}}}}}}}} :: RecStrMap Boolean
Let's assume that the RecStrMap type satisfies the Functor requirements. We can then replace Functor f => f with RecStrMap, giving:
(a -> b) -> RecStrMap a -> RecStrMap b
The implementation of RecStrMap#map would need to be recursive. The problem, though, is that certain values are ambiguous. Is {a: {b: {x: 0, y: 0}}} a value of type RecStrMap :: Number, or does {x: 0, y: 0} represent a "point" meaning that the correct interpretation is RecStrMap :: { x :: Number, y :: Number }. If the latter is what we intended, we'll find map will not do as we expected: the function we provide will be applied to numbers rather than to "points". It's therefore impossible to treat JavaScript objects as recursive string maps while preserving the forall a requirement (if our data type limits the types of values it can contain, it is not a functor).
One could define a RecStrMap data type by providing Leaf and Tree constructors to resolve the ambiguity. The representation of the value in question might then be:
Tree({level1: Tree({hello: Leaf('Deepworld')}), hello: Leaf('shallowworld')})
Were R.map to operate recursively over arbitrarily nested string maps _represented by plain JavaScript objects_ it would no longer be lawful. We could no longer perform this transformation:
> R.map(votes => (votes.yeas / (votes.yeas + votes.nays) * 100).toFixed(1) + '%', {CA: {yeas: 11, nays: 4}, NY: {yeas: 8, nays: 4}})
{CA: '73.3%', NY: '66.7%'}
Most helpful comment
Let's take a step back to consider the type of
map:{level1: {hello: 'Deepworld'}, hello: 'shallowworld'}is incompatible with this function since we cannot resolveainf a. IffisStrMapwe haveand
as
avalues, and there is no _standard_ type of which allavalues are members.We could, though, define a recursive string map type: a data type mapping strings to values of a certain type _or_ to recursive string maps of that same type.
Every value of type
StrMap awould also be a member ofRecStrMap a. For example:But unlike the StrMap type, the RecStrMap type would support arbitrary nesting:
Let's assume that the RecStrMap type satisfies the Functor requirements. We can then replace
Functor f => fwithRecStrMap, giving:The implementation of
RecStrMap#mapwould need to be recursive. The problem, though, is that certain values are ambiguous. Is{a: {b: {x: 0, y: 0}}}a value of typeRecStrMap :: Number, or does{x: 0, y: 0}represent a "point" meaning that the correct interpretation isRecStrMap :: { x :: Number, y :: Number }. If the latter is what we intended, we'll findmapwill not do as we expected: the function we provide will be applied to numbers rather than to "points". It's therefore impossible to treat JavaScript objects as recursive string maps while preserving theforall arequirement (if our data type limits the types of values it can contain, it is not a functor).One could define a RecStrMap data type by providing
LeafandTreeconstructors to resolve the ambiguity. The representation of the value in question might then be:Were
R.mapto operate recursively over arbitrarily nested string maps _represented by plain JavaScript objects_ it would no longer be lawful. We could no longer perform this transformation: