The one exception I would make is for discriminated unions / sum types / ADTs / etc and pattern matching. I find any language without these to be extremely hard to safely construct data models with. Although in truth it’s an incredibly hard thing to retrofit (e.g. variants in C++17).
Rust: too hard and too sanctimonious
Haskell: just too hard
Seriously @ppqq this is what you need to do for Dart 3.0
To play devil’s advocate, I still see issues pop up about Python 2.x vs. 3.x sometimes. JS and the whole transpiation idea for being able to use new language features (ES6/ES7+), while being portable across environments (i.e. code is transpiled to ES5) is pretty cool.
That being said, as someone who works with JS full time (and specifically a large AngularJS 1.x app), it can definitely get overwhelming. At the current moment, it seems like building a larger, modern web app that adheres to best practices involves understanding and using different things for the view layer (React/Vue/Angular 2), CSS-in-js (styled-components, glamour, etc.), the data layer (Redux), adding in strongly-typed benefits (TypeScript), immutable data structures (Immutable.js), and then building/bundling/packaging everything (Webpack, NPM, Grunt, Gulp, etc.).
I tried to sit down and start looking at what a rewrite of our angular app would look like with a collection of these newer technologies, and it was very overwhelming…this is part of the reason why I’ve been against adding dependencies in the side projects I’ve worked on, including the teletype docs enhancements
I am aware of it, and have heard good things about it too, I just don’t do any web dev anymore. I do think the Haskell/ML style of separating the type signature from the function implementation to greatly aid readability. C style function declaration does not cope well with the templates and traits that C++ and Rust respectively add into the mix.
That is a fair point. The pain point was always the redefinition of the string type to be an opaque Unicode text type, rather than a byte array. You see the same issue in a lot of other pre-Uniciode languages (Haskell has 3 common string types in use, String, Text and ByteString, yuck!). I suspect history will prove them correct in making the change, but that they could have made the transition easier.
To anyone on the fence, 3.6 has enough interesting new features over 2.7 that it makes the change worthwhile. I particularly like formatting strings, and pathlib from 3.4 is really nice too.
That is a very wise decision.
A few years back I decided I want to make a printable picture-coded calendar for my pre-school daughter. It would list the days she was at nursery, weekends, birthdays, what her new Mr. Men / Little Miss Book was this week, etc. It’s been incredibly useful, particularly with understanding the concept of days and weeks.
I was really impressed by it. It made it really easy to quickly build small composable bits of UI. Until 6 months later when I tried updating my package.json, then it all went to crap. So now it’s stuck using 2 year old versions of everything. I do worry what I’d do if I were doing this professionally, running old dependencies is a great way to get Equifaxed.
Just a little aside - I’ve been writing Haskell (casually) for the last 3 months & once you realize that you don’t need to understand monads & functors to get in the door it’s actually pretty accessible, albeit with a somewhat different mental model of data & control flow. Pattern matching, ADTs and list comprehensions are sorely missed when I’m writing C day-to-day. These 3 things are much closer to the way I think about software, than the traditional imperative approach.
Now if only it would run on a microcontroller, I wouldn’t be compelled to partake in this thread!
I guess I was a being a bit tongue in cheek. I also write Haskell a fair bit these days too, I started learning about 2 years ago (2nd attempt). It’s now my go to programming language. I even understand what a Monad is!
I’m just saying that there is an opening for a less full-on language that also brings pattern matching and ADTs, etc. All new programming languages should include them, and as you say they behave much closer to how we think about software.
No microcontrollers… but there is CλaSH which compiles down to Verilog/VHDL. I’m not sure how mature it is, and in truth it’s really a DSL embedded in Haskell, with it’s own set of idioms.
Rust is definitely getting close to being practical with embedded hardware, and has a lot of stuff from Haskell. (Traits in Rust are like Typeclasses in Haskell.)
I also completely forgot about Swift, which may end up gaining popularity outside of the Apple ecosystem. I’m don’t know much about it, and have no idea how approachable it is as a language.
You’ve probably used them more than you know. If you have a value wrapped inside of something, e.g. an optional in Swift. Then when you bind1 the inner value into a new value (via some computation). That’s a amore^H^H^H^H^H, I mean, that’s monadic.
A bit of Googling tells me that Swift has a null-coalescing operator (??), which is basically a monadic bind.
1 sometimes also called flatMap
Ooooo interesting. Never really used Lua. I do know it uses 1-based indexing, which will make the mathematicians happy.
I got into it a tiny bit - kind of interesting & fun! I paired it with an icestick fpga, open-source yosys toolchain, & a ‘usbstreamer’ usb->i2s soundcard. Got some basic stuff working like an attack-decay envelope follower. The really wicked feature of clash for fixed-point DSP design is the fixed-point fractional type system.
I would argue audio domain is not well-suited to the ‘pure hardware’ approach. If you ‘directly’ synthesize a moderately complex DSP algorithm in hardware, physical size (number of gates) gets huge rather rapidly. So you quickly end up running out of gates if your logic is clocked directly at a typical audio samplerate.
Say you have like 10 biquad filters in your algorithm, you have to choose between either:
a) using 10 x as many gates
b) designing aux logic which shovels biquad state for a single ‘biquad accelerator’ to & fro a RAM several times per audio frame.
Even straightforward algorithms can get pretty hairy when you play this game. Something more involved/conceptual like lines/waves!? zoinks!
It would be so cool if we could somehow use clash’s fractional types to write blackfin-optimised fixed-point DSP objects for aleph! Even after much practice, moving floating point ideas to fixed-point blackfin-ised C is laborious…
I know nothing about FPGAs. But I’m okay with Haskell…
The above strikes me as the kind of thing that one can generalise in Haskell…
ramBacked :: (KnownNat n, RamStorable d, RamState d s)
=> (Signal a -> s d (Signal b)) -- the signal you wish to multiplex, has access to the state-like monad RamState to store and retrieve contents
-> Signal (Vec n a)
-> Signal (Vec n b)
The above is really rough, as it’s based on a very quick parsing of the types that Clash uses. And I haven’t made any attempt to deal with clock rates in the type signatures.
I also don’t know if Clash is able to deal with Signals that operate internally at a faster rate.