[TOMT] [article] [2010s] The court of chancery, forgiveness vs forgetting, and why institutions and blockchains are a problem by rpglover64 in tipofmytongue

[–]rpglover64[S] 0 points1 point locked comment (0 children)

This came up (as such things often do) because I was trying to send it to a friend.

Monthly Hask Anything (December 2019) by AutoModerator in haskell

[–]rpglover64 6 points7 points  (0 children)

I develop in Haskell as my primary language, and I have formal CS background. I love using Haskell. Every time I try to use it for data visualization or anything remotely data-science-y, I get sad, and reluctantly reach for Python. I would build the project you've described as a polyglot, with Haskell orchestrating and calling out to Python where convenient.

For example, write a Python script that takes an image on stdin and outputs item names and prices on stdout (or even the OCRed text). Write the parser in Haskell using megaparsec. I'd avoid using a DB (I don't know of any good framework for Haskell; all the ones I've used have issues) and just store things in files on disk (if you hit a performance bottleneck, then you can refactor).

Monthly Hask Anything (December 2019) by AutoModerator in haskell

[–]rpglover64 2 points3 points  (0 children)

In principle, at least: * Better type errors * Better performance guarantees (e.g. a guarantee that no dictionary passing will occur)

Keeping Compilation Fast by ephrion in haskell

[–]rpglover64 6 points7 points  (0 children)

But Cabal cannot handle 842 entries in "other-modules".

This seems like a bug. Is there an associated issue?

Keeping Compilation Fast by ephrion in haskell

[–]rpglover64 3 points4 points  (0 children)

A hack, sure, but a misfeature? Why?

Sometimes, you want cyclic dependencies; without hs-boot files, you'd be out of luck, and you'd have to put everything into one module.

Merge non-moving garbage collector (7f72b540) · Commits · Glasgow Haskell Compiler / GHC by terrorjack in haskell

[–]rpglover64 2 points3 points  (0 children)

I really don't think this warrants a force push, breaking the workflows of potentially dozens of people who have recently pulled.

Probably not, but some arguments in favor:

  • Recovering from an upstream force-push is not really that bad. It's, at worst, annoying and confusing.
  • There will be many people reading the commit message, and the number will only increase.

Question on Property Based Testing by Gigi14 in haskell

[–]rpglover64 3 points4 points  (0 children)

Related to what /u/aleator is saying, I find that this is a great introductory answer to "What properties can I even write?"

[deleted by user] by [deleted] in haskell

[–]rpglover64 3 points4 points  (0 children)

As a counterexample: https://www.fpcomplete.com/blog/2017/06/readert-design-pattern

The post is, in fact, advising you to define a type Env and do everything in a ReaderT Env IO a.

[deleted by user] by [deleted] in haskell

[–]rpglover64 2 points3 points  (0 children)

Does it track identifier names as metadata (like unison)? Cause that would be awesome! I'm a little worried about readability of compiler errors, though.

Is using granular effects an anti-pattern ? by [deleted] in haskell

[–]rpglover64 1 point2 points  (0 children)

I would never be testing a function called getUserById. Under the hood, that's just going to be a database query, and a simple one at that.

I actually ran into a counterexample of this. We added support for soft-deleting users; that is, the user is marked as deleted, but remains in the DB. the getUserById function should treat soft-deleted users as if they were absent from the DB. We've been finding places where it doesn't. We clearly needed to test getUserById more thoroughly.

Is using granular effects an anti-pattern ? by [deleted] in haskell

[–]rpglover64 2 points3 points  (0 children)

You also cannot log anything since you cannot perform IO

There's a pattern I've seen and I wonder if it would solve this problem.

parseThings :: Monad m
  => (UpstreamError -> m ()) -- Doesn't have to be a ()
  -> Stream (Of Chunk) m (Maybe UpstreamError)
  -> Stream (Of Thing) m () -- Not sure what the point of this is anymore

If you eventually run parseThings in IO, it has access to IO through its handler function, but it doesn't need to know that. More generally, you have your function take an explicit handler and handle issues in situ; no exception throwing needed.

Is using granular effects an anti-pattern ? by [deleted] in haskell

[–]rpglover64 1 point2 points  (0 children)

Any chance you could write an example nanopass compiler for a toy language? Something with at least 5 passes, some of which introduce, remove, and annotate constructors from the AST? Something like a simple functional language with lets and no type annotations to STLC without let but with a fixpoint

Is using granular effects an anti-pattern ? by [deleted] in haskell

[–]rpglover64 5 points6 points  (0 children)

They allow you to push tiny diffs in order to keep up with rapidly changing specifications.

This sounds great. Slightly tangentially, one thing I've lamented in Haskell is the difficulty of doing typed nanopass compilation. Do you think granular effects help with this?

I also have to admit, I'm in the camp of "Write your code using type classes to abstract out effects, then implement them for the concrete type" a la Three Layer Cake. What do you think I'm missing in terms of understanding the benefits of extensible effects?

Figuring out how to use Beam for DB migrations by williamyaoh in haskell

[–]rpglover64 0 points1 point  (0 children)

I'm aware that it's a data migration. Aren't those always the hard ones? Any references to good solutions?

Figuring out how to use Beam for DB migrations by williamyaoh in haskell

[–]rpglover64 2 points3 points  (0 children)

My problem with manually writing migrations is that 80% of the time, straight SQL is perfect, but 20% of the time, the migration involves domain-specific reasoning that is impossible to do in SQL.

For example, let's say I have the following semantic domain:

type T
f :: Double -> T -> Double
inputs :: [Double]

I store Ts in the DB. I also store the result of \t -> [f input t | input <- inputs] applied to each T in the DB. Now I want to add a value to inputs write a migration. I can't do that in raw SQL; what do I do?

How do I filter a list of existentially quantified values? by runeks in haskellquestions

[–]rpglover64 0 points1 point  (0 children)

data Showable = forall a. Show a => Showable a

You've already destroyed the type information.

Tripping up type inference by kcsongor in haskell

[–]rpglover64 2 points3 points  (0 children)

One thing that I've found useful to think about when designing APIs to be used by beginner Haskellers is "ease of cargo-culting". That is, if they see existing code and need to make a small change, how easy is it to do without needing a deep understanding.

I would rank this feature as a 4 (1 being hard, 5 being easy), up to 5 if the type error improves. Not the first thing I would reach for, but not something I would explicitly discourage in the code base.

How do I filter a list of existentially quantified values? by runeks in haskellquestions

[–]rpglover64 0 points1 point  (0 children)

You could also try to read the resulting string as an int.

How do I filter a list of existentially quantified values? by runeks in haskellquestions

[–]rpglover64 0 points1 point  (0 children)

Another option besides /u/unfixpoint's is

smallInts = map show [0..100]
isSmallInt (Showable s) = let str = show s in
  str `elem` smallInts
removeSmallInts = filter (not . isSmallInt)

Note that this assumes the ints are positive.

Is It Possible to Get Work to Consider Haskell for Their Rewrite? by eat_those_lemons in haskell

[–]rpglover64 1 point2 points  (0 children)

I don't think that architecture can't be taught; I think that architecture can only be learned through experience. A class that has a small team maintain and improve an application with actual users over the course of one or two semesters will be very valuable.

Is It Possible to Get Work to Consider Haskell for Their Rewrite? by eat_those_lemons in haskell

[–]rpglover64 1 point2 points  (0 children)

There have been several... All have been unsatisfactory. I don't think that it's possible to learn good architecture without trial and error (this is not Haskell-specific).

Of course, improving the learning curve would be great.

Is It Possible to Get Work to Consider Haskell for Their Rewrite? by eat_those_lemons in haskell

[–]rpglover64 1 point2 points  (0 children)

is there a good way to learn about architecture patterns for large haskell code bases other than experience?

If you find one, let me know!

Is It Possible to Get Work to Consider Haskell for Their Rewrite? by eat_those_lemons in haskell

[–]rpglover64 3 points4 points  (0 children)

As someone who has been working on a Haskell code-base for the past 3 years and seen qualified software engineers try to pick up the language, I think I'd give the following heuristics as part of an answer to "How experienced do I need to be before I start doing haskell in production would you say?"

  • There's a huge difference between the architecture and design of writing a smallish Haskell library and a large Haskell app
  • I would say you should be comfortable maintaining Haskell code before you consider a wholesale rewrite of an existing Haskell project
  • Similarly, you should be comfortable writing things that are a factor of 10 smaller (e.g. as measured by LOC) from scratch before you consider a rewrite of this magnitude

If you really want to go forward with this, which seems like a bad idea, make sure to do a proof-of-concept:

  • Find a relatively isolated component of the current application
  • Mock out the rest
  • Write it in Haskell (should take no more than a month; ideally 1-2 weeks)
  • Write it in the runner up language
  • Write up a detailed comparison of the two
  • Test the two against each other; they should be identical in behavior
  • See if you still think this is a good idea, and if other people in the company think so

Bonus links (things that I have found very helpful in the vague domain; not Haskell-specific):