0

How do you qualify the name of a field within a function like this:

let sortedIssues :: [Issue] = sortOn updatedAt issues

I have an issues table with an updated_at column. However, I also have another table with an updated_at column so the compiler does not know which one I am referring to in the above function.

Trying to qualify the above as Issue.updatedAt does not work since there is no Issue module. The IHP-generated types are all within just one module as well, so importing Generated.Types does not help.

  • How is `Issue` defined? It seems the problem is that you aren't distinguishing between the two tables at the *type* level, only at the term level. – chepner Apr 06 '23 at 13:24

1 Answers1

2

It's best to use dot notation here to avoid this problem:

let sortedIssues :: [Issue] = sortOn (.updatedAt) issues

This short form notation is a shorthand for this:

let sortedIssues :: [Issue] = sortOn (\issue -> issue.updatedAt) issues
Marc Scholten
  • 1,351
  • 3
  • 5
  • Brilliant. Thank you! As soon as I saw your answer, I realized I misunderstood what I was doing previously. It was the first time for me to use the `sortOn` function and for some reason I ended up writing it in that way without realizing that what I had written was shorthand form of a lambda function. Now it makes sense. Thank you. – stephenbenedict Apr 06 '23 at 13:41
  • @stephenbenedict If you're referring to what you wrote in the question, then what you say is not right: `updatedAt` is not shorthand for `\x -> updatedAt x`. It's rare that the difference matters, but it really is more than just a different syntax. `\x -> updatedAt x` creates a new function that is definitely not bottom even if `updatedAt` is. – Daniel Wagner Apr 07 '23 at 21:33
  • @DanielWagner Thank you for the explanation. If what I wrote is not shorthand for the lambda expression then what is it doing? I am not able to understand what you wrote here `but it ... is definitely not bottom even if updatedAt is.` – stephenbenedict Apr 09 '23 at 02:08
  • @stephenbenedict In your question, you write `updatedAt`. There is nothing that this syntax is "doing" -- `updatedAt` is simply the name of a function, and `sortOn` takes a function as its argument. So you are passing an argument to a function, just like you would be if you wrote, say, `log 5` or `putStrLn "Hello, world!"`. The `"Hello, world!"` isn't "doing" anything, it just *is*. I give a small caveat: in the answer here, the poster references "dot notation". It is possible they are referring to [this](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/overloaded_record_dot.html) (1/?) – Daniel Wagner Apr 14 '23 at 13:39
  • syntax, or it is possible they are simply referring to standard section syntax. In either case, the code in this answer *is* shorthand for a lambda. (Caveat finished.) With regards to "is bottom"/"is not bottom" -- "bottom" is a technical term that, in this context, groups together infinite loops and exceptions. Even if infinite computation is required to work out what `foo` is (a thing that must happen before you supply it an argument), the computation `\x -> foo x` does *not* require infinite computation; it is immediately available for application to an argument. Practically speaking, (2/?) – Daniel Wagner Apr 14 '23 at 13:43
  • when using GHC as your Haskell implementation, all this means is that `\x -> foo x` requires a single extra memory allocation (of one or two machine words) compared to `foo` and one extra pointer dereference on each call, so as I said it is rarely relevant; but for example if you have a loop that repeatedly adds one layer of lambda-ness at each iteration you can get yourself in trouble. (And this has come up in some relatively high-profile libraries, because it is not always so obvious when you have mistakenly added a layer of lambda!) (3/3) – Daniel Wagner Apr 14 '23 at 13:44