These are chat archives for ramda/ramda

22nd
Jul 2015
Scott Christopher
@scott-christopher
Jul 22 2015 01:10
@TheLudd A common approach for managing types that represent nested monads is via monad transformers.
You can see an example of a proposed Reader Transformer here: ramda/ramda-fantasy#55
Hardy Jones
@joneshf
Jul 22 2015 01:10
hah, i was typing that just now
:)
Scott Christopher
@scott-christopher
Jul 22 2015 01:10
:D
Though I imagine heavily stacked monad transformers could potentially get quite confusing in javascript without the assistance of a type system.
David Chambers
@davidchambers
Jul 22 2015 01:13
The secret debugging tool?
R.tap(R.compose(console.log, R.toString))
Hardy Jones
@joneshf
Jul 22 2015 01:13
yeah, that'd be hell to deal with if you're not careful
David Chambers
@davidchambers
Jul 22 2015 01:13
I use this all the time to understand what types of values are actually flowing through my pipelines.
Scott Christopher
@scott-christopher
Jul 22 2015 01:14
@davidchambers I usually have that pinned at the top of my scripts while developing
David Chambers
@davidchambers
Jul 22 2015 01:14
:D
Scott Christopher
@scott-christopher
Jul 22 2015 01:14
Was incredibly useful while poking around with the ramda build script
Hardy Jones
@joneshf
Jul 22 2015 01:14
so probably make it weaker than Chain and it'll be easier to understand.
you know, since all the rest are composable
David Chambers
@davidchambers
Jul 22 2015 01:15
I should really write a drop-in replacement for R.pipe which gives the equivalent of R.pipe(R.tap(log), f, R.tap(log), g, R.tap(log), h, R.tap(log)) for pipeLog(f, g, h). ;)
Scott Christopher
@scott-christopher
Jul 22 2015 01:16
R.intersperse(R.tap(log), fns)
Scott Sauyet
@CrossEye
Jul 22 2015 01:23
@tencircles: That looks like useWith, which has desparately needed a better name since it was first created.

@davidchambers:

Nothing() is the empty Maybe value, is it not?

I think that depends on how you want to define your Monoid. That's always a possibility. We have an odd habit in JS of trying to think of Maybe as the type rather than Maybe a, and that confuses things a lot.

Scott Christopher
@scott-christopher
Jul 22 2015 01:28
My understanding was that the empty of Maybe should be Monoid m => Maybe m, such that it relies on the empty of the value it contains.
Assuming the empty (monoid) implies concat (semigroup), there is no sane way of concating Maybe types unless you can concat their values.
Hardy Jones
@joneshf
Jul 22 2015 01:39
there are a few monoids for Maybe a
Scott Christopher
@scott-christopher
Jul 22 2015 01:43
I guess there are also First/Last instances of monoids for Maybe types.
Scott Sauyet
@CrossEye
Jul 22 2015 02:45
@scott-christopher: I believe you can define a lawful Monoid over Maybe a where the identity is Just a.identity, the usual one uses Nothing for an identity. I find this strange, but a long discussion in the FantasyLand Gitter room convinced me that this is, if nothing else, the most common version.
Ludwig Magnusson
@TheLudd
Jul 22 2015 09:06
@scott-christopher Do you have a good link to some post explaining the purpose and mechanisms of transformers? Or would you like to give an explanation here? :)
Aldwin Vlasblom
@Avaq
Jul 22 2015 09:19
Hi, is there a prettier way to express a(x) || b(x) || c(x)then to use R.either twice? (R.either(R.either(a, b), c)) I feel like I'm looking in the wrong direction if this is what I'm doing.
Ludwig Magnusson
@TheLudd
Jul 22 2015 09:19
@Avaq anyPass
Aldwin Vlasblom
@Avaq
Jul 22 2015 09:20
But doesn't that return a boolean?
I want the return value of a, b or c depending on truthyness.
Ludwig Magnusson
@TheLudd
Jul 22 2015 09:20
Isnt that what you want? So does either
I was wrong
The documentation is a bit confusing. The signature says that the passed in functions to either should return a boolean. That is how I have used it.
Aldwin Vlasblom
@Avaq
Jul 22 2015 09:24
R.either: "returns the result of the first function if it is truth-y and the result of the second function otherwise"
But I want to do this exact thing with n functions.
Aldwin Vlasblom
@Avaq
Jul 22 2015 09:29
anyPass just returns true if any of the functions returned a truthy value, but that value is lost.
Ludwig Magnusson
@TheLudd
Jul 22 2015 09:30
It looks like there is no such function
What is your use case?
Aldwin Vlasblom
@Avaq
Jul 22 2015 09:33
Really it's just a bit of an excersize as I'm learning Ramda: err.stack || err.message || err.toString() -> R.either(R.either(R.prop("stack"), R.prop("message")), R.toString)
Ludwig Magnusson
@TheLudd
Jul 22 2015 09:34
Perhaps you could use cond
But I am not sure it would be pretty. :P
It would also be possible to hook this up with transduce.
But I also think that may be a little to complex
Aldwin Vlasblom
@Avaq
Jul 22 2015 09:43
I don't think transducers would exactly be the right tool. The way I understand it; transducers are just a way to create a step function which can be given to any process in order to transform the steps it takes. They're useful for any process that takes a succession of steps (like processing arrays or streams, listening to events, etc), which is not what I'm doing I think.
I'm just bouncing my understanding of transducers off you - if you don't mind - I've been reading about them and hope I understand them now.
I'm looking at cond. :)
Oh cond looks like a really close match, except I think I'd have to do: R.cond([[a,a], [b,b], [c,c]]) - which is a bit odd.
Ludwig Magnusson
@TheLudd
Jul 22 2015 09:47
Well you could use transduce for this too I beleive. R.transduce(R.find(isTruthy), R.defaultTo, null, list). Not sure it works and it isn't all that declarative. I'd write my own function instead
No, looks like i misunderstood your case. Forget my transducerthing
Ludwig Magnusson
@TheLudd
Jul 22 2015 09:52
One question: what would your function return if nothing is truthy?
The last result?
Aldwin Vlasblom
@Avaq
Jul 22 2015 11:00
Yeah, just like JavaScript expressions do.
Hardy Jones
@joneshf
Jul 22 2015 13:49
@TheLudd if you compose Functors you get a Functor, if you compose Applys you get an Apply, if you compose Applicatives you get an Applicative, if you compose Chains you get an Apply, if you compose Monads you get an Applicative. Monad transformers allow you to compose Monads and get a Monad.
where compose means Maybe (Identity a) or [Either a b] or Future String [Maybe a] or something.
Although more general, so it's more like (Functor f, Functor g) => f (g a)
So, if you program to the interface of composed Functors for example, you know you can always map your way to the actual value.
If you program to the interface of composed Monads, you have no such guarantee
Ludwig Magnusson
@TheLudd
Jul 22 2015 13:53
@joneshf And if I want to combine Maybe with another monad then I need to have a Maybetransformer?
Hardy Jones
@joneshf
Jul 22 2015 13:53
Pretty much, but I was a bit unclear.
If you know the other Monad up front, like Maybe [a] then you can say things about it (like you can chain the list because you know it's a list). it's when you don't know both Monads up front, like Monad m => Maybe m a or more generally (Monad m, Monad n) => m (n a) (here you can only say that you for sure can ap, map and of all the way down, it's only as powerful as an Applicative).
eh, this explanation isn't very good
don't take this for the definitive guide
Hardy Jones
@joneshf
Jul 22 2015 13:58
Suffice to say, when you compose Monads you don't necessarily get a new Monad out of it. But if you use a monad transformer with another Monad, then you get a new Monad out of it.
There are better explanations of the hows and the whys.
Ludwig Magnusson
@TheLudd
Jul 22 2015 14:00
but like... Reader has the runproperty and Future has fork. What do I get if I user Reader transformer with Future? Can I fork and/or run it?
Hardy Jones
@joneshf
Jul 22 2015 14:03
Sure, you should be able to do that because you know both of your data types up front.
you know you have a Reader and you know you hve a Future, so you can talk about operations on each piece.
Ludwig Magnusson
@TheLudd
Jul 22 2015 14:05
Ok. I can figure out the details by experiment.
But if you read the case I had earlier... I make a request to a db with an id as an input and the matching object as an output.. I need Future because it is async and I need Maybe because there may be no match for the id. Should I then use a Future transformer with a maybe?
Hardy Jones
@joneshf
Jul 22 2015 14:45
Here's a better explanation, if you compose two Monads then there's no way to write the function chain2 :: (Monad m, Monad n) => m (n a) -> (a -> m (n b)) -> m (n b), which is an attempt to chain through both Monads. And you can prove that there's no way to write that function, Monad just isn't powerful enough to do that. So the composition of two Monads is not a Monad. If instead you have a monad transformer and a Monad, then you can write that function.
You can do that, sure. Or you can use the regular Future.
You might have an easier time with a transformer depending on how you're manipulating the value.
if you have a bunch of functions a -> Maybe b then you're going to have to lift all over the place, so it'll be just as crufty as using Future by itself.
Ludwig Magnusson
@TheLudd
Jul 22 2015 14:49
Ok
Hardy Jones
@joneshf
Jul 22 2015 14:51
you don't really get a nice dsl for transformers until you move to the mtl-style, which I don't think anyone has done in js yet.
Or if it would even work well enough.
Ludwig Magnusson
@TheLudd
Jul 22 2015 14:52
I will explore transformers. What is mlt? =)
Hardy Jones
@joneshf
Jul 22 2015 14:53
It's another haskell library for transformers. It allows you to talk more abstractly about transformers.
uses type class resolution to choose the correct functions.
Hardy Jones
@joneshf
Jul 22 2015 15:03

You go from something like increment :: Monad m => StateT Int m () (this is how most transformers are encoded) to something like increment :: MonadState Int m => m () (mtl-style).

In the first case, you have to be aware of where the StateT Int m a is in the stack. So you might have something like lift $ increment or increment or lift $ lift $ lift $ increment depending on where you use it in the stack.

In the second case, you can just call increment anywhere in the stack and it "should" do the right thing.

Which is pretty cool, if you're using a MonadReader r m in part of your stack, you can just ask anywhere and get the r, like db config or whatever, rather than trying to figure out where you are in the stack and how many lifts are necessary.
Tor Bruce
@trbrc
Jul 22 2015 16:43
hey
am I wrong if I think there is nothing like lodash's xor in ramda?
Tor Bruce
@trbrc
Jul 22 2015 16:46
not really. _.xor([1,2,3,4], [7,6,5,4,3]) => [1, 2, 7, 6, 5]
R.difference([1,2,3,4], [7,6,5,4,3]); //=> [1,2]
Tobias Pflug
@gilligan
Jul 22 2015 16:47
oh, my bad. right
Tor Bruce
@trbrc
Jul 22 2015 16:47
:)
basically, i need a way to toggle a thing in an array, so add it if it wasn't there, or remove it if it was.
and i thought of lodash's xor.
i can't think of any simple way to do it with ramda with less than ≈3 different calls
Tor Bruce
@trbrc
Jul 22 2015 17:02
well, now i just did it with splice, but isn't this something that should be within ramda's scope?
David Chambers
@davidchambers
Jul 22 2015 17:03
Sounds like a useful Ramda function, certainly.
This isn’t efficient:
R.difference(R.union(a, b), R.intersection(a, b))
Tor Bruce
@trbrc
Jul 22 2015 17:05
right. i remember doing something similar in a project that used underscore, which also doesn't have xor.
David Chambers
@davidchambers
Jul 22 2015 17:05
It can be written quite neatly, though:
R.converge(R.difference, R.union, R.intersection)
Tor Bruce
@trbrc
Jul 22 2015 17:05
but it's more contrived than it should be.
David Chambers
@davidchambers
Jul 22 2015 17:05
Mind opening an issue?
Tor Bruce
@trbrc
Jul 22 2015 17:07
sure, can do!
Scott Sauyet
@CrossEye
Jul 22 2015 19:23
@TheLudd: "What's mlt"? Why, it's better than true love: https://youtube.com/watch?v=T7i9Xh15534.
"Sonny, true love is the greatest thing in the world. Except for a nice MLT, a mutton, lettuce and tomato sandwich, where the mutton is nice and lean and the tomato is ripe. They're so perky. I love that. "
Ludwig Magnusson
@TheLudd
Jul 22 2015 20:57
@CrossEye Couldn't be clearer :)