6 ms·
Haskell Mini-Patterns Handbook
- whateveracct 6y agoThis is great. I can say I've used and encountered literally all of these techniques many times in every Haskell codebase I've joined and built. The concise cost/benefit analysis very helpful.
- johnisgood 6y agoI do not write Haskell, but this is a neat site.
- jbawn 6y agoThanks for this. The tasks are a nice touch!
- hackingthenews 6y agoAnyone else have trouble with the page on firefox? I get a giant "kowainik" written on the forefront of the page, and I don't know how to close it.
- jjjbokma 6y agoI am using Firefox and it works without problems. 79.0 on macOS Mojave.
- uryga 6y agolooks fine on 79.0 (Windows, w/ ublock)
- hackingthenews 6y agoI tried with Chrome and it worked.
- zzo38computer 6y agoDeleting it in the inspector works.
- gspr 6y agoWorking fine on Firefox 68.11.0-ESR on Linux for me.
- glutamate 6y agoThe whole "this code is problematic because... " section on Boolean blindness reminds me of the worst caricatures of left-wing narratives of oppression based on PhD-level Critical Theory. Look, a lot of the other patterns are interesting but I really think that if you are getting into criticising code because it has "Boolean blindness" you are probably getting a bit lost in navel gazing. Do you really have nothing better to do?
- uryga 6y agodo you have any criticisms with actual substance? why do you consider those techniques "navel gazing"?
- glutamate 6y agoI really feel that too many rules like this lead beginners astray and focus on issues that make very little difference in delivering a product. If beginners see a list like this, and start re-factoring the code to remove "Boolean blindness", that's likely not the best way for them to spend their time and the code may become more verbose in the process. I prefer not to dwell on negativity about code, as long as it does the job and is implemented in a reasonably simple manner. I think in the Haskell community sometimes there can be an unhealthy tendency to nitpick the implementation details.
- ffreire 6y agoI wouldn't consider them rules inasmuch as they're things to keep in mind when working in a Haskell codebase, in much the same way GoF has been useful for OO programmers for decades. Can you write code without using a pattern from GoF? Sure. Will it work? Probably. Does that make GoF useless? No, I'd think not. This type of content is immensely valuable for beginner and practitioner alike because it starts to build a shared language with which to talk about how codebases are organized :)
- alephu5 6y agoAs a beginner you're just trying to keep your head above water and get the damn thing to compile. For me at least I cared more about that than making the code pretty. Moreover I don't see much harm refactoring your code with these patterns and maybe losing time, because most people learn haskell off the job.
- gowld 6y agoThis is a beautiful start but much more content. Send PRs to kowainik.
- chrischen 6y agoThese patterns are not only applicable to Haskell but FP and programming in general. I am using them with a Typescript codebase.
- misja111 6y agoThis is a gem. I have been looking for this kind of clear and to the point explanations of common Haskell patterns for a long time.
- mlazos 6y agoThis is a great post, I’ve seen a lot of those patterns before and it’s nice to have them in one place! One criticism I have though is I’m not sure about the advantage of phantom types, it seems like boilerplate to me. I feel like generalized algebraic data types are a strictly better pattern to follow to solve the issue of restricting type variable bindings to specific types.
- danidiaz 6y agoPhantom types can be useful when modelling currency: the "implementation" stays the same but you want to avoid summing two different currencies by mistake. https://ren.zone/articles/safe-money https://ren.zone/articles/safe-money
- chriswarbo 6y agoI introduced phantom types to a codebase recently, although it was Scala rather than Haskell. The code was using arrays of bytes, where: - Some contain plaintext, some contain ciphertext - Some contain keys, some contain data - The keys themselves exist in plaintext and ciphertext forms (data keys generated by AWS KMS) - Some keys were used for signing/verifying, some were used for encrypting/decrypting - Some arrays contain Base64 data (for embedding in JSON), some contain unencoded data Using 'Array[Byte]' would work, but would be error-prone. Using distinct types or wrappers like 'Base64[Plaintext[Key[Signing]]]' would require lots of extra definitions, and wrapping/unwrapping scattered around the code. Phantom types let me use type signatures with the right amount of specificity and polymorphism as needed, whilst the code itself was the 'straightforward' version without wrapping/unwrapping.
- nybble41 6y ago> I feel like generalized algebraic data types are a strictly better pattern to follow to solve the issue of restricting type variable bindings to specific types. GADTs which don't store a value based on one of their type parameters are still making use of phantom types. The key concept with a GADT is that you can have type variable binding(s) (whether phantom or concrete) which are determined by the constructor. If you aren't taking advantage of that then you're probably just defining an ordinary data type using GADT syntax.
- johndoe42377 6y agoThe most deadly sin with Haskell is introducing unnecessary redundant abstractions to impress other people. Imagine aircraft engineers will do that. Up to (but not including) NonEmpty lists everything was fine.
- deleted 6y ago[deleted]
- gspr 6y agoDo you have some examples?
- whateveracct 6y ago> Up to (but not including) NonEmpty lists everything was fine. "but not including" how in the world is NonEmpty redundant abstraction?