rel8
rel8 copied to clipboard
Should Rel8 functions be in a curry-friendly (haskell style) or infix-friendly (sql / operator style) argument order?
This was discussed offline at some point, but I thought I'd just double-check that this is really what we want? The feature is still brand new so it seems worth getting it right.
A colleague made the mistake of assuming ilike takes arguments in the same order as postgresql defines. I can easily see myself doing the same and being confused about why the query result are "wrong". I hardly spend any time looking at documentation for something as simple and familiar as like.
Taking two possible patterns for using ilike:
filter (ilike "Rel%" . packageName) =<< each haskellPackages
and
do
package <- each haskellPackages
where_ ("Rel%" `ilike` packageName package)
Do we really lose much with the unflipped version?
filter ((`ilike` "Rel%") . packageName) =<< each haskellPackages
and
do
package <- each haskellPackages
where_ (packageName package `ilike` "Rel%")
Here's our conversation when we chose this argument order:
Shane: I can understand why you've done it the way you have (consistent with SQL), but I'd be tempted to flip the order of the parameters, that feels ab it more Haskelly to me
But I guess if we're calling it the same thing SQL calls it we might as well use SQL's order too
Ollie:
You mean to match functions like elem?
Shane: Yeah
Ollie:
Hmm, no, elem is this order I think - elem thing pattern, like thing pattern
Shane:
> :t elem
elem :: (Foldable t, Eq a) => a -> t a -> Bool
Are you sure?
Ollie:
Yea? I consider t a the "pattern" to find "thing" in
Shane: This isn't exactly the same thing, but:
> SELECT 'foobarbaz' LIKE '%bar%';
?column?
----------
t
(1 row)
> elem "bar" ["foo", "bar", "baz"]
True
Ollie: I guess it's worth looking at usage. To take a concrete example, we have
partNumber `like` "PANASONIC/%"
Or
"PANASONIC/%" `like` partNumber
When you put the two next to each other, it kinda looks commutative anyway
Shane: Yeah, well if you're using the infix form anyway then it doesn't matter
But I think like "PANASONIC/%" is the more useful curried form
Ollie:
Yea, it probably is. like "PANASONIC/%" . partNumber
I'll make that change and a comment clarifying the order, and why we've chosen it
I should also add I know the incident you're referring to, and I'm pretty sure that was me who caused the problem, not said colleague! We (CircuitHub) had our own ilike definition that didn't have flipped parameters. When I switched us over to the released version of ilike, I missed updating the existing function call. At least, I think that's what happened.
Sorry yeah, it was a migration from older ilike you say, not a mistake.
I think like is a (perhaps unfortunate) side effect of the so called 4GL influence on SQL syntax.
This seems like a similar familiarity trade-off as Elm's flipped andThen and andMap forms, but at least andThen / andMap is named differently than bind >>= and ap...
(My main worry is that if we change this later everyone's queries will break silently like ours did)
Perhaps a final bit of consideration I could add:
It looks to me like postgresql functions may in general be more infix-friendly than curry-friendly.
E.g.
starts_with(string, prefix)
string `starts_with` prefix
as opposed to the more curry-friendly
(starts_with prefix) string
repeat(string text, number int)
string `repeat` int
as opposed to the more curry-friendly
(repeat int) string
I think I'm generally more in favor of curry-friendly when writing haskell code from scratch, but perhaps worth considering whether we generally want to thinly wrap or generally want to reorder.
I think either is probably ok, but probably good to make the decision explicitly. I'll rename the issue to reflect the broader question...
The answer of course is rewrite GHC to flip the order of arguments when infixing.
Sorry, not a useful contribution, but i couldn't help myself becuase always felt infixing functions should work that way.
I saw a thing recently that suggested using & instead of backticks to achieve the same effect, i.e., "foobar" & ilike "%oo%". Not sure if I'd ever write code like that myself but it's an option.