@joneshf Interesting point. Come to think of it, most of ramdas functions probably mutate state of local private variables.

However, no

However, no

`Maybe`

, `Either`

I have seen implemented in JavaScript give you a pure interface since attributes assigned to `this`

are publicly available.
I’m trying to understand how to organize data in a functional manner. Would love some help: http://bit.ly/1G6duvX

@vikfroberg to me it makes sense to divide the problem into two parts:

- reducing the input into a list where each item is a separate event with a date
- applying a formatting function into each item in that list with map

after 1. you can also easily sort the list by date with

`R.sortBy`

@raine Thanks, I'm going to give it a shot. What I'm struggling with is the part where I convert one event to number of days. What would I use to accomplish that? R.times?

```
> R.range(event.startDate, event.endDate + 1)
[ 21, 22, 23 ]
```

you can build a list of Dates from that

write a function that takes a day of month and returns a Date object, then map over the list

@raine Thanks, got it working!

@raine Now is there anything I can do different/better? I would love to use currying instead of the callback functions, but not sure how to though: http://bit.ly/1OeaSWx

you could call the map function

`formatEventStr`

or something
```
var eventsPerDay = R.reduce(function(acc, event) {
var days = R.range(event.startDate, event.endDate + 1);
return R.concat(acc, R.map(R.assoc('date', R.__, event), days));
}, [], events);
```

try to place more functions in variables instead of data. then compose those functions together to avoid intermediary values

i think you should be able to replace

`reduce`

with `chain`

so you dont' have to worry about initial values and `concat`

and whatnot
```
var eventsPerDay = R.chain(function(event) {
return R.range(event.startDate, event.endDate + 1).map(function (date) {
return {title: event.title, date: date};
});
}, events);
```

then continue with what @raine just posted :)

so you get something like:

```
var eventsPerDay = R.chain(function(event) {
var days = R.range(event.startDate, event.endDate + 1);
return R.map(R.assoc('date', R.__, event), days);
}, events);
```

@raine Thanks! Didn't know about R.assoc!

@joneshf Awesome! I was looking for a "flatMap" function but couldn't find it, chain does the trick!

you can then extract the range out

```
function dateRange(event) {
return R.range(event.startDate, event.endDate + 1);
};
var eventsPerDay = R.chain(function(event) {
return R.map(R.assoc('date', R.__, event), dateRange(event));
}, events);
```

from there it's pretty hard to go pointfree without getting a bit convoluted

since

`event`

needs to be passed into both `dateRange`

and the function in `map`

you could do it, but it's probably more readable this way

For the sake of learning, how would I do that?

Hmm, this will get long, so I apologize in advance.

also, there might be an easier way than this if there's some function that is basically

`ap`

for functions in ramda.
also that's the punchline ^

so the idea is that if you can make

`R.map(R.assoc('date', R.__, event)`

and `dateRange(event))`

take their `event`

argument, then you can say use `pipe`

to string them together.
`dateRange(event)`

is trivial to make this happen, just use `dateRange`

the other is also pretty easy, just pipe with the inner function, to

`map`

: `R.pipe(R.assoc('date', R.__), R.map)`

although, i'm not actually sure how

`R.__`

will handle being within that pipe like that
it might actually be better to get rid of it

`R.__`

doesn't do anything useful in the last position.
so it'll have the same behavior as above the non-piped version then?

oh

i see what you mean

Nothing to do with

`pipe`

.
okay, then

`assoc :: String -> a -> {k: v} -> {k: v}`

from the docs, so we want `String -> {k: v} -> a -> {k: v}`

then that's

`R.flip(R.assoc('date'))`

Part of the reason for avoiding a points-free solution here is that it simply adds nothing. Here is a version of

`dateRange`

:
so what we actually wanted was

`R.pipe(R.flip(R.assoc('date')), R.map)`

so now both parts accept the

`event`

argument
and we just need some way to thread it through each part

`var dateRange = R.converge(R.range, R.prop('startDate'), R.compose(R.inc, R.prop('endDate'))`

That is not nearly as readable as the original version.

it turns out that what we want is the

`Applicative`

instance for functions
it goes by many names, so don't be taken aback by

`Applicative`

`Reader`

, `S`

combinator, `Starling`

, etc
and it actually seems like

`converge`

as well
Not sure if it's the same thing or not.

Recently discussed correct sig for it in #1035

`(x1->x2->… -> z) -> ((a->b->… -> x1), (a->b->… -> x2), …) -> (a->b->… -> z)`

yeah, it's a variadic version

which works for this

so we can use

`converge`

to supply `event`

to both functions
and then we just need a converging function that applies one to the other

so let's look at some types real quick

`dateRange :: {startDate :: Int, endDate :: Int, ...} -> [Int]`

`R.pipe(R.flip(R.assoc('date')), R.map) :: {...} -> [a] -> [{date :: a, ...}]`

for some approximation of types. here i'm using

`...`

to indicate some other fields
then we see that in both functions, they take an object, so we want

The

`converge`

to end up taking an object as our argumentThe

`event`

object is exactly the one we want to pass to `converge`

So, given the signature from @CrossEye above, we want converge to have the type:

```
([Int] -> ([Int] -> [{date :: a, startDate :: Int, endDate :: Int, ...}]) -> [{date :: a, startDate :: Int, endDate :: Int, ...}]) ->
( ({startDate :: Int, endDate :: Int, ...} -> [Int])
, ({startDate :: Int, endDate :: Int, ...} -> [Int] -> [{date :: a, startDate :: Int, endDate :: Int, ...}])
) -> [{date :: a, startDate :: Int, endDate :: Int, ...}]
```

I dunno, it's pretty bad any way

When they get this bad, sometimes we resort to

`R.nthArg`

. Our more likely, give up on points-free.
you could use some synonyms

```
let A = [Int]
let B = [{date :: a, startDate :: Int, endDate :: Int, ...}]
let C = {startDate :: Int, endDate :: Int, ...}
```

Then you get

`(A -> (A -> B) -> B) -> ((C -> A), (C -> A -> B)) -> B`

@CrossEye yeah, I agree, it's way convoluted. but @vikfroberg wanted to know for the sake of learning :)

This is amazing!

in any case, we've already got

`C -> A`

, which is `dateRange`

, and `C -> A -> B`

is `R.pipe(R.flip(R.assoc('date')), R.map)`

. so we just need `A -> (A -> B) -> B`

.
and that's

`R.flip(R.call)`

!
so we can slap it all together as...

`R.converge(R.flip(R.call), dateRange, R.pipe(R.flip(R.assoc('date')), R.map))`

then it's point free, and also pointless :P

So you can now say:

`var eventsPerDay = R.chain(R.converge(R.flip(R.call), dateRange, R.pipe(R.flip(R.assoc('date')), R.map)), events);`

Very nicely done.... even if pointless. :smile:

This is going to take some time to digest, but you have no idea how valuable this is! :D

@vikfroberg I'm glad you didn't walk away half way through.

I think it was saved by having

`converge`

exist
otherwise would've had to greenspun up a reader.

but

@CrossEye i think that means for ramda-fantasy, reader can be made simpler

or maybe not simpler

but it could be implemented in terms of converge

Perhaps. I've never really tried to understand Reader.

what do Applicative and Reader have in common? i thought Reader is basically like an environment for function

There's one other somewhat interesting function that's related.

`useWith`

has this signature:
`(x1 -> x2 -> ... -> z) -> ((a -> x1), (b -> x2), ...) -> (a -> b -> ... -> z)`

@raine

`Reader`

has an `Applicative`

instance. remember `Applicative`

isn't a data type, it's a specification/interface/typeclass/trait/module/whatever.
also

`Reader`

is exactly `Function`

or at least it should be.
so in that sense, it doesn't really make sense to have it as an abstraction, since it should have the same behavior for

`map`

,`ap`

,`chain`

, etc that functions do. What you really want is the transformer version, `ReaderT`

, so that you can compose it with arbitrary `Monad`

s.
and if you happen to compose

`ReaderT`

with `identity`

you get `Reader === Function`

.