I ❤ BQN and Haskell
Vložit
- čas přidán 27. 06. 2024
- LeetCode Problem: leetcode.com/contest/weekly-c...
BQNPAD: bqnpad.mechanize.systems/
BQN Solution: github.com/codereport/LeetCod...
Haskell Solution: github.com/codereport/LeetCod...
Chapters:
0:00 Intro
2:16 BQN Solution
5:59 Haskell Solution
10:04 Solution Comparison
11:50 Outro
Follow me on GitHub: github.com/codereport
Follow me on Twitter: / code_report
Follow me on LinkedIn: / codereport
liftA2 in Haskell (in Control.Applicative module) is a builtin phi combinator
Enough with the trivial examples! Now let's see a 3D game engine in BQN. Can you do it in 25 lines of code or less?
I'd settle for a useful commandline tool.
If I had to guess, the part that computes game state probably could be, if you omit the part that does I/O (controls, graphics, audio)
@@derelbenkoenig so we just need like C bindings and we are ready to go
CBQN has some basic C bindings available.
I’ve been working on an ASCII-based array language called Noda. Here’s how I’d solve it:
*abs(>>nums(+) - > and
❤❤ Haskell ❤❤
I love these videos where there are multiple languages. You get to see what is kinda the same, and what really has to be different. If it was just one language I would get it less. I think I learn a lot from seeing the difference at work to make sense of both.
you are a great explainer
I love it. Can you make a video comparing the differences between BQN and APL? They seem quite similar, but I wonder why they say BQN is better
That video implicitly exists already inside this one: czcams.com/video/8ynsN4nJxzU/video.html and also this one: czcams.com/video/UogkQ67d0nY/video.html
your haskell function looks very clean. it uses an extra function declaration and a (.:) operator import, however. here's my attempt at solving with just the haskell prelude. :]
leftRightDifference = zipWith ((abs .). (-)) . (tail . scanr (+) 0) (init . scanl (+) 0)
Was hoping to see the applicative instance of reader (S combinator) come up! Nice
That's ugly... Why in the world would you be against using things outside of the prelude? You know the prelude is universally considered terrible right? People are so weird
That BQN had shift primitives and the Under operator did help. Something for my SugarBQN namespace.
Beautiful
Instead of defining the `phi` combinator yourself, you can also look at the `Control.Arrow` (and `Control.Category`) module, which gives rise to the following Haskell solution:
```
((scanl (+) 0 >>> init) &&& (scanr (+) 0 >>> tail)) >>> uncurry (zipWith (-)) >>> map abs
```
When I'm doing some hard leet code problems, I struggle to find a functional solution, it seems that those problems are created in a way to be solved with dynamic programming. Can you do a video solving some problems tagged hard on leet code or any other site using the functional paradigm?
Can you please add common lisp sbcl to the problems videos solutions
How do you guys program in APL? Do you have a custom keyboard that contains all apl symbols? Do you just have a tab open with ascii tables?
Most editors you type ` (backtick) and then a key. And you very quickly memorize the symbols. `i is iota. You can try here: tryapl.org/
Do you think that languages like BQN and APL should be used in the making of commercial products or just as a fun exercise?
I think they are great for both. BQN is a very young language but there are already a bunch of companies that use APL in production: github.com/interregna/arraylanguage-companies
@@code_report I always get thrown off how many of the companies doing fancy code stuff are in finance, I guess it makes sense since finance companies are likely hiring mathematicians and not just regular software developers
Would be nice to see C++ and Rust solutions
Here is a Rust solution using a array library in Rust (but unfortunately it's not public atm): pastebin.pl/view/5caf93b6
Hello, this is very interesting. I have been using a Lisp (LispE by Naver) that provides some APL-like instructions and I came up with the following solution:
(zipwith (\(x y) (fabs (- x y))) (cons 0 (pop (\\ '+ r))) (consb (cdr (reverse (-\\ '+ r) )) 0))
\\ and -\\ are the scan and back-scan operators and '\' introduces a lambda function... Very similar to your own solutions...
Cool
I would assume Ctrl+L clears the screen in GHCi. Also yeah structural Under is so cool
Thanks! I think knew that at one point but forgot. And agree, under is awesome!
When you type :! In ghci you can do shell commands. So :!clear will clear the screen
The rust version should be,
nums
.iter()
.copied()
.zip(nums
.iter()
.rev()
.copied())
.scan((0, 0), |acc, (l_ele, r_ele) {
let ret_val = *acc;
*acc = (acc.0 + l_ele, acc.1 +r_ele);
ret_val
}).map(|(a, b)| a - b)
.map(i32::abs)
.collect()
A lot more verbose but that's because it's a bit different approach
has BQN replaced APL as your favorite language?
Yes.
@@code_report what about J?
Which city which conference ? If its close I might attend
LambdaDays in Krakow: www.lambdadays.org/lambdadays2023
Can we get maintainable code in BQN? I'm talking a project with a shelf life of more than 6-9 months.
Maybe
I thought the B combinator was
B f g x y = f x (g y)
Are there different naming schemes for them?
No, that is the D combinator. See here: combinatorylogic.com/table.html
@@code_report Oh, yeah. I was thinking of B1 the Blackbird, but I was also wrong there too
didn't take you long to switch alleigence away from APL :P
haha, APL is still my second favorite languages. BQN has more combinators and sort primitives though 😂
lol @ 3 glyphs being 'overly verbose'🤣
I got rank 379 in this contest
Nice!
BQN FTW
Yeah that's quite cool. But i still prefer the readablity and simplicity of plain C:
/*Caller free the result*/
int *solve(const int *array, size_t size) {
int *result = malloc(size * sizeof(int));
int *lsum = calloc(size, sizeof(int));
int *rsum = calloc(size, sizeof(int));
for (size_t i = 1; i < size; i++) {
lsum[i] = lsum[i - 1] + array[i - 1];
rsum[size - i - 1] = rsum[size - i] + array[size - i];
}
for (size_t i = 0; i < size; i++)
result[i] = abs(lsum[i] - rsum[i]);
free(lsum);
free(rsum);
return result;
}
No need to know about any weird concept or some obsure std feature. plain, readable procedural code.
one person's "weird concept" is another person's "intuitive pattern"
@@computer-love I didn't say it wasn't intuitive. I mean't that if you need to use the specific language to understand what does the symbols actually mean and implies.
The power (IMO) of procedural is that you can follow the execution as it happen. This lead to more obvious and easy to understand code. much cleaner than APL or BQN
(no, having a bunch of cryptic characters isn't by any mean clear).
If you learned any language of the C family (java, c++,... and any language which support procedural pattern) you can easily reason and understand what the code actually mean. In small, easy problem like this one both are good, but i have my doubt about the readability of a big BQN project.
Don't get me wrong, i really some feature of functional language (i love the Maybe / Error / Option monad) I just think using every feature of the language makes code less pretty and easy to follow.
Haha this is the other extreme :) I also don't know BQN, but I have played around with some haskell in Uni. I really liked these list operations like fold, map, filter. I think for me the most readable approach would be something like Python Numpy or C# Linq, which is from my understanding close to the haskell solution
the only reason that feels simple is because we're used to C. i tutor and the concepts in your code are not remotely simple for most students.
the most popular languages derive from procedural or C style programming, so of course that's what you're comfortable reading. as for following the execution, again, that's a function of familiarity with the language. one can follow the BQN code just fine, not to mention taking it apart piece by piece to watch literal data mutation is trivial.
Why use x rated videos when you can read BQN solutions?
crude ngn/k solution (as a function) before watching: t:{a:(+\x)-|+\|x;a*1 -1a
what
Control.Arrow might come handy with uncurry
(&&&) :: (a -> b) -> (a -> c) -> (a -> (b,c))
`uncurry` is in the Prelude i think
@@ponirvea yes (&&&) is not however
[ abs (l - r) | l
what do you think of?
leftRightDifference = (zipWith ((abs .) . (-)) . init . scanl (+) 0) (tail . scanr (+) 0)
also, _"Haksell FOURTH fav language"_ ??? what happened ???
😢
1. BQN
2. APL
3. Clojure
4. Haskell
I toggle between Clojure and Haskell but I find Clojure more useful in practice.
@@code_report Hearing you choose Clojure over Haskell hurts my soul 😛
Looking forward to your next video!
I think you meant instead of . before init. Also, you can remove 2 sets of parenthesis 🙌
@@WilcoVerhoef no.. i meant (.) .. My code works, I was just asking what he thinks of it.
(abs .) . (-)
is the point free version of
\x y -> abs $ x - y
but sure or fmap for functions (->) is indeed the same as composition or (.)
f g = f . g
so you could write
(abs ) (-)
but I think you would have to be some sort of masochist (and sadist) to write instead of . 😃
@@noomade You're right, both (.) and () works. Weird.
Love it! A great video to pause and ponder. This was my attempt in BQN +`∘»{|𝔽-𝔽⌾⌽}
In fact it's enough to do: |+`⌾⌽-+` The shifts are not needed!