Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should Rel8 functions be in a curry-friendly (haskell style) or infix-friendly (sql / operator style) argument order? #164

Open
rehno-lindeque opened this issue Feb 10, 2022 · 7 comments

Comments

@rehno-lindeque
Copy link

rehno-lindeque commented Feb 10, 2022

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%")
@ocharles
Copy link
Contributor

ocharles commented Feb 10, 2022

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

@ocharles
Copy link
Contributor

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.

@rehno-lindeque
Copy link
Author

rehno-lindeque commented Feb 10, 2022

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...

@rehno-lindeque
Copy link
Author

(My main worry is that if we change this later everyone's queries will break silently like ours did)

@rehno-lindeque
Copy link
Author

rehno-lindeque commented Feb 10, 2022

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...

@rehno-lindeque rehno-lindeque changed the title Is the flipped versions of like and ilike really worth the currying convenience? Should Rel8 functions & operators be in a curry-friendly (haskell style) or infix-friendly (sql style) argument order? Feb 10, 2022
@rehno-lindeque rehno-lindeque changed the title Should Rel8 functions & operators be in a curry-friendly (haskell style) or infix-friendly (sql style) argument order? Should Rel8 functions be in a curry-friendly (haskell style) or infix-friendly (sql / operator style) argument order? Feb 10, 2022
@maninalift
Copy link

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.

@shane-circuithub
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants