Posts

This profile is from a federated server and may be incomplete. Browse more on the original instance.

DiazCarrete, to haskell
@DiazCarrete@hachyderm.io avatar

AFAIK, there's not an easy way in Haskell to inspect at the type level what type a field has in a record.

What I mean is that that there doesn't seem to be a type family like

type FieldType :: Type -> Symbol -> Type

that we could invoke in ghci like

:kind! FieldType Person "age"

Why would I want this? For libraries like servant and rel8 that use parameterized records where the types of the fields vary heavily with the type parameter.

I guess I could hack it using generics. 🤔

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

"hack it using generics"
^ oh god, my poor memory. I actually did already implement something like this back in the day, using generics.

https://hackage.haskell.org/package/red-black-record-2.1.4.0/docs/Data-RBR.html#t:Value

DiazCarrete,
@DiazCarrete@hachyderm.io avatar
DiazCarrete, to random
@DiazCarrete@hachyderm.io avatar

If your branch has a good number of commits since it diverged from main, rebasing can sometimes seem like a Sisyphean task. Because each commit is applied independently, you often end up resolving merge conflicts again and again in the same places, conflicts that a merge would make you resolve together in one go.

To avoid that, I sometimes squash together all the commits in my branch before rebasing on top of main. But then of course I lose the structure of the separate commits.

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

@nshephard Actually, I've found some links that talk about rerere helping even for single rebases (?) so maybe I'm wrong. But I'm still unsure about why it would work 🤔

🔗 https://mindup.medium.com/enable-git-rerere-for-easy-merging-303c6f2dacd3
🔗 https://stackoverflow.com/questions/10601541/smarter-rebase-avoiding-redundant-work

DiazCarrete,
@DiazCarrete@hachyderm.io avatar
DiazCarrete, to haskell
@DiazCarrete@hachyderm.io avatar

The library lets you construct queries using a monadic interface.

Interesting bit: "Rel8 has a fairly unique feature in that it’s able to return not just lists of rows, but can also return trees."

https://rel8.readthedocs.io/en/latest/cookbook.html#tree-like-queries

image/png

mangoiv,
@mangoiv@functional.cafe avatar

@DiazCarrete admittedly this was on a fairly weak machine

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

Post about Entity Framework, touching on how to extract across a foreign key relationship
https://blog.ploeh.dk/2023/09/18/do-orms-reduce-the-need-for-mapping/
https://twitter.com/ploeh/status/1703782709422657939

DiazCarrete, to haskell
@DiazCarrete@hachyderm.io avatar

When building #haskell Servant applications with persistence, a common (?) pattern is to request a database connection from a pool in the callback we pass to "hoistServer" https://hackage.haskell.org/package/servant-server-0.20/docs/Servant-Server.html#v:hoistServer and then pass the connection down to the handler using ReaderT https://github.com/danidiaz/comments-project/blob/3bb720124b31f0a8e351751bdcc6651ed75d9e27/comments/lib/Comments/Runner.hs#L57
It works, but I'm kinda unhappy about it because it forces you to use ReaderT in those intermediate components that lie between the top-level handler and the repository component which actually uses the connection. 😕

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

You might say "Well, that's not a problem, just make those intermediate components that don't care about the connection polymorphic over MonadUnliftIO! Later, when composing the application, they will be injected a repository that does know about the ReaderT and the connection. Problem solved."

That's true, but what if I wanted those intermediate components to be as dumb as possible? Just plain records of functions in IO, no monad transformers, and no polymorphism over the monad, either?

DiazCarrete, (edited )
@DiazCarrete@hachyderm.io avatar

"I got rid of ReaderT and now my application is hanging by a thread"
https://discourse.haskell.org/t/i-got-rid-of-readert-and-now-my-application-is-hanging-by-a-thread/9330

DiazCarrete, (edited ) to haskell
@DiazCarrete@hachyderm.io avatar

I know that Megaparsec doesn't backtrack automatically and that you have to use "try" for that, but this behavior of "many" was unexpected. Why oh why doesn't it parse the final space?
https://stackoverflow.com/a/78355045/1364288
Maybe I didn't read the documentation thoroughly, but I don't think it's actually spelled out in the Haddocks?

exa,
@exa@mastodon.online avatar

@DiazCarrete
+1 for the other suggestion here: do not eat space before the lexemes (as beginner tutorials tend to show) -- always eat it after the lexemes (and only after the lexemes!), and do it reliably. Hard-learned lesson.

BoydStephenSmithJr,
@BoydStephenSmithJr@hachyderm.io avatar

@DiazCarrete IIRC, we don't "try" by default because it can cause excessive backtracking, and having that even be a possibility holds references to things, increasing memory usage, and decreasing performance.

So, yeah, anytime you want to "noncommittally consume", you have to use try explicitly.

DiazCarrete, to haskell
@DiazCarrete@hachyderm.io avatar

friendship ended with ScopedTypeVariables, TypeAbstractions is my new best friend
https://serokell.io/blog/ghc-dependent-types-in-haskell-3

BoydStephenSmithJr,
@BoydStephenSmithJr@hachyderm.io avatar

@DiazCarrete That's what I do, yes. newtype Semantic2 = MkSemantic2 { unSemantic2 :: Semantic1 }

Though sometimes I do something different, like newtype Subset = AssertSubset { asSuperset :: Superset } for things where the rep. sharing is more practical, even if the syntax isn't actually the same, like Email/Text or PhoneNumber/Int64 since construction will generally be through something like isEmail :: Text -> Either ParseFailure Email or inputPhone :: Natural -> Maybe PhoneNumber

kosmikus,
@kosmikus@functional.cafe avatar

@DiazCarrete I think both are nice to have.

DiazCarrete, to vim
@DiazCarrete@hachyderm.io avatar

9.1 released, including support for classes in Vimscript! Now I can finally adopt it as my my primary programming language. (Just kidding, of course... It already was.)
🔗 https://www.vim.org/vim-9.1-released.php
🔗 https://vimhelp.org/vim9class.txt.html#vim9-class

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

Unironically good programming advice from :h vim9-class

jaror,
jaror avatar

@DiazCarrete with type classes in Haskell my personal ideology is to avoid them unless you're very sure that they are really a good model of your domain and they have specific laws. But indeed, many classes and instances - in base even - don't satisfy that.

DiazCarrete, to haskell
@DiazCarrete@hachyderm.io avatar

"Nesting APIs and ReaderT environments with Servant"
https://nicolashery.com/nesting-reader-environments-servant/

fubaroque,
@fubaroque@mastodon.social avatar

@DiazCarrete Why oh why would anybody try to fix a missing manual with a bl**dy YouTube video?! 🥴 🤔 😠

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

@fubaroque Making videos about topics that one feels are underexplained is good.

That said, the reference documentarion for the Spring IOC container is already good https://docs.spring.io/spring-framework/reference/core/beans.html but it's a reference, not focused in the big ideas and motivation behind dependency injection / AOP.

DiazCarrete, to haskell
@DiazCarrete@hachyderm.io avatar

In Servant, the ServerError type has an Exception instance
https://hackage.haskell.org/package/servant-server-0.20/docs/Servant-Server.html#t:ServerError
You might speculate that when throwing a ServerError using liftIO . throwIO in a Handler, the ServerError is automatically caught and served as a response, but it ain't so: it's treated as just another exception, and the response code is 500.

Instead, you should throw ServerErrors using "throwError", re-exported from the "Servant" module.
https://hackage.haskell.org/package/servant-server-0.20/docs/Servant.html#v:throwError

#haskell

image/png

DiazCarrete, (edited )
@DiazCarrete@hachyderm.io avatar

@BoydStephenSmithJr I don't think it's a bad idea!

I believe we can impement in Servant the throwIO behavior I mentioned earlier by catching (some) runtime exceptions in the callback passed to "hoistServer" and re-throwing them in the "proper" way expected by Handler. https://hackage.haskell.org/package/servant-server-0.20/docs/Servant-Server.html#v:hoistServer

BoydStephenSmithJr,
@BoydStephenSmithJr@hachyderm.io avatar

@DiazCarrete I think that universally quantified x might be a problem, but I suppose it depends on the type of your re-throw mechanism.

DiazCarrete, to programming
@DiazCarrete@hachyderm.io avatar
clementd,
@clementd@framapiaf.org avatar

@DiazCarrete That being said, when working with servant in Haskell, I ended up putting the public API types in a separate cabal package, that was depended upon by both the server implementation and the clients. This made a lot of things considerably simpler

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

@clementd Yeah, I can see how it would be useful. "package by layer" wins in that case I guess.

DiazCarrete, to random
@DiazCarrete@hachyderm.io avatar
DiazCarrete,
@DiazCarrete@hachyderm.io avatar
DiazCarrete,
@DiazCarrete@hachyderm.io avatar
DiazCarrete, to haskell
@DiazCarrete@hachyderm.io avatar
DiazCarrete,
@DiazCarrete@hachyderm.io avatar

I have wondered about this myself:

(24:30) https://youtu.be/fFCcvsbCrH8?t=1468

"registry"-like approaches do seem to make it easier to reuse previously assembled application contexts because the wiring is done through a dictionary-like data structure. You can easily overwrite any key with a different implementation, or with a mock.

Relatedly, they also seem to make it easier to draw diagrams of component dependencies:
https://hackage.haskell.org/package/registry-0.6.1.0/docs/Data-Registry-Dot.html
https://github.com/danidiaz/cauldron/blob/700dafb64ed932eee8b66356e35196c586d7e24c/lib/Cauldron.hs#L123

jaror,
jaror avatar

@DiazCarrete That slide seems to misrepresent effect systems. It is easy to replace just runInputConst:

runAllEffects (runInputDifferently program)

The runInputDifferently effect handles the Input Config effect and it leaves an unused Input Config in the list of effects. So the runInputConst config handler in runAllEffects will not be used.

DiazCarrete, to random
@DiazCarrete@hachyderm.io avatar

cabal init --non-interactive --no-comments --dependency="base, servant, servant-server, servant-blaze, blaze-html, blaze-htmx"

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

@clementd Do you know of any comparison between blaze-html and lucid2?

clementd,
@clementd@framapiaf.org avatar

@DiazCarrete Not really. Not sure how outdated https://chrisdone.com/posts/lucid/ is.

What won me over was consistent naming and optional attributes

DiazCarrete, to haskell
@DiazCarrete@hachyderm.io avatar

Rel8 is a #Haskell library that teeters between "looking at the instances provides much useful information" and "looking at the instances causes psychic damage".
https://hackage.haskell.org/package/rel8-1.5.0.0/docs/Rel8.html#t:Table

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

Relatedly, it would be a nice feature for Haddock if the instances local to a module could be sorted and grouped for the purposes of documentation and telling a story.

Like "These are the instances for tuples of various sizes" or "this is the base case and these are some instances that recurse".

DiazCarrete,
@DiazCarrete@hachyderm.io avatar
DiazCarrete, (edited ) to random
@DiazCarrete@hachyderm.io avatar
DiazCarrete,
@DiazCarrete@hachyderm.io avatar
DiazCarrete,
@DiazCarrete@hachyderm.io avatar

I didn't have luck configuring cabal-docspec on CI, even as it worked fine locally.

I had more luck configuring the traditional "doctest" package 🔗 https://hackage.haskell.org/package/doctest following the recommended instructions.

🔗 https://github.com/danidiaz/cauldron/blob/9ada1f7a3c62ab71fd7763e10f3930f30ea0e635/.github/workflows/haskell-ci.yml#L66
🔗 https://github.com/danidiaz/cauldron/blob/9ada1f7a3c62ab71fd7763e10f3930f30ea0e635/.github/workflows/haskell-ci.yml#L182

One advantage of "doctest" is that it's on Hackage.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • JUstTest
  • kavyap
  • DreamBathrooms
  • mdbf
  • InstantRegret
  • ngwrru68w68
  • magazineikmin
  • thenastyranch
  • Durango
  • rosin
  • Youngstown
  • slotface
  • khanakhh
  • tacticalgear
  • megavids
  • ethstaker
  • cubers
  • cisconetworking
  • normalnudes
  • modclub
  • everett
  • osvaldo12
  • GTA5RPClips
  • Leos
  • anitta
  • tester
  • provamag3
  • lostlight
  • All magazines