5 ms·
APL Interpreter – An implementation of APL, written in Haskell (2024)
- deleted 1y ago[deleted]
- behnamoh 1y agoDepending on your personality type (perfectionist or pragmatic), this is either the best of both worlds or the worst.
- valcron1000 1y agoMy favorite language used to interpret my most hated language (used both professionally). There are several things I disagree with regarding Haskell but it's understandable given that this is OP's first time using the language (like a "monad's internal state"), but I want to highlight one particular observation: > This uncertainty of time of evaluation also makes catching errors difficult, because calling catch on the function that throws the error will not necessarily catch that error It's important to distinguish between imprecise exceptions (ex. calls to `error `, `undefined`, and the like) and synchronous exceptions (async exceptions are not important for the article). > Catch must be called on the function that forces evaluation on that error. This is something that is hard to trace, and something that types don’t help much with. The types are actually the most important part here! Synchronous exceptions cannot be thrown by pure code (as long as we're not dealing with escape hatches like `unsafePerformIO`), while IO code can throw and catch all kind of exceptions .
- tome 1y agoRegarding catch, yes, I agree types help, but they can help even more! I suggest an IO-wrapper effect system (mine is called Bluefin; effectful is also a good choice). Then there is absolutely no ambiguity about where an exception can be handled. There is exactly one place -- no more, no less. It makes dealing with exceptions very easy. https://hackage.haskell.org/package/bluefin-0.0.16.0/docs/Bluefin-Exception.html https://hackage.haskell.org/package/bluefin-0.0.16.0/docs/Bl...
- rak1507 1y ago[flagged]
- valcron1000 1y agoCare to elaborate?
- rak1507 1y agoWell, you've said you used APL professionally, but judging by https://news.ycombinator.com/item?id=31368299 https://news.ycombinator.com/item?id=31368299 it was in a university project.
- ofalkaed 1y agoRegarding that link >GNU is free but pretty much abandoned. Support for Windows was (is?) nonexistent. GNU APL was never abandoned, dev just went a long time without doing a proper release. I believe the Windows issue is just with cygwin, never looked into it since I don't use Windows.
- asgraham 1y agoWhat a wild thing to comment. a) “professional” writ large often encompasses academic research, even though it’s also often specifically used in contrast. Language is weird like that. Former and current academics like to have a term for all the stuff we’ve been paid to do, and we usually default to “professional experience” (though current academics do usually say “research experience” because you’re right that professional has the default connotation of corporate employment). b) the project seems to have been over 2000 lines of APL. That’s not the “small” student project you’re implying, in any language, and in APL that’s quite substantial.
- rak1507 1y agoMost of it is boilerplate or written like it is Java, so it is pretty small compared to any real world projects. To me professional implies production/real world/paid work, not just an unfinished academic project.
- instig007 1y ago> Apparently Haskell’s performance isn’t that bad, but I don’t plan on using Haskell for anything that is remotely performance-sensitive. Trying to optimize Haskell code does sound like an interesting problem, but it might be a lost cause. When the dude uses `foldl` over lists and `foldr` with `(*)` (numeric product) it is not the language that's the lost cause.
- kccqzy 1y agoIn case anyone who doesn't know Haskell: both of these are beginner level mistakes. Using `foldl` causes space leaks and turns your O(1) space algorithm to O(N) space for no good reason. And using `foldr` over lists is good when you are dealing with unevaluated lists and want list fusion, but not when they already exist in memory and will continue to do so. And that doesn't even include the obviously wrong choice of data structure, built-in Haskell lists are singly-linked lists not arrays. There are Array types and Vector types (both come with GHC so no extra dependency needed) that are more appropriate for implementing APL in the first place.
- itishappy 1y ago> And using `foldr` over lists is good when you are dealing with unevaluated lists and want list fusion, but not when they already exist in memory and will continue to do so. What's the preffered approach?
- farrellm23 1y agoUsually you want `foldl'` (with ' at the end), the strict version of `foldl`. It prevents the creation of intermediate thunks, so effectively a tail recursive iteration over the list in constant space. `foldr` I almost never use, but it would be for: the return value is a lazy list and I will only need to evaluate a prefix.
- zoul 1y agoThe naming conventions are nicely sadistic.
- howerj 1y agoIs there an implementation of an APL language (or other any other array language) written in *readable* C that is around 1000 LoC? There are for LISP, FORTH, Prolog, TCL and the like.
- ofalkaed 1y agoNot that I have found, closest is an incomplete one done in python. https://mathspp.com/blog/tag:lsbasi-apl#body-wrapper https://mathspp.com/blog/tag:lsbasi-apl#body-wrapper
- itishappy 1y agoWhat, you don't like Arthur's style? https://www.jsoftware.com/ioj/iojATW.htm https://www.jsoftware.com/ioj/iojATW.htm https://github.com/kparc/ksimple/blob/main/ref/a.c https://github.com/kparc/ksimple/blob/main/ref/a.c Slightly less factiously, the ksimple repository has a version with comments. https://github.com/kparc/ksimple https://github.com/kparc/ksimple https://github.com/kparc/ksimple/blob/main/a.c https://github.com/kparc/ksimple/blob/main/a.c Note, these aren't APL, but they are in the same family of array languages.
- xelxebar 1y agoUnlikely, at least for what I think you mean by "readable" here. APL isn't really one of these exhibitions of computational simplicity in the way of the languages you mention. It's inventor, Kenneth Iverson, was more focused on the human side of thinking in and using the language. Forth, Lisp, et al are quite easy to implement, but they require considerable library layers on top to make them useful for expressing application-level logic, even if we just focus on the pure functions. APL, on the other hand, has a larger core set of primitives, but you're then immediately able to concisely express high-level application logic. Are you looking for a kind of reference implementation for learning purposes? If so, I'd say the best route is just go with the docs. Arguably the Co-dfns compiler is a precise spec, but it's notably alien to non-practitioners.
- ofalkaed 1y agoAny pointers on how to get better at expressing high-level application logic in APL? Any good resources on programming in APL? So far I have only found tutorials and basic stuff for learning APL but not much on applying APL. I am slowly improving and think I sort of get it but probably don't.
- nickzelei 1y agoInteresting read! On a semi-related topic: I tried learning Haskell this past weekend out of curiosity that I last tried it some 10+ years ago while still in college. I found resources for it scant. Coming from more modern languages/tooling like Go/Rust, I also struggled quite a bit with installation and the build/package system. I tried the stack template generator for yesod/sqlite and after some 15 minutes of it installing yet another GHC version and building, I eventually ctrl+C'd and closed out of the window. Maybe this was a unique experience, but I'd love some guidance on how to be successful with Haskell. I've primarily spent most of my professional years building web services, so that was the first place I went to. However, I was taken aback by how seemingly awful the setup and devex was for me. I've always been interested in functional programming, and was looking to sink my teeth in to a language where there is no other option.
- itishappy 1y agoMy understanding is that Cabal has more or less supplanted Stack. Use GHCup to install everything, then use `cabal init`, `cabal run`, or `cabal repl` like you would in Go/Rust. Stack builds on top of Cabal, and used to solve a bunch of problems, but the reasons for it's existence are no longer super relevant. It still works totally fine if that's your thing though.
- nickzelei 1y agoThat is so interesting and is a point where GPT has failed me if this is true. My understanding was the stack was the choice due to having better ergonomics over cabal. Apparently that isn't true? I Found that stack init was pretty decent at setting up a project structure, but can't say I tried cabal init. I initially installed ghcup via homebrew but found that did not set things up correctly and had to follow the install from their site, which made things work more smoothly.
- simonmic 1y agostack does generally have better UX. cabal hasn't supplanted it (and won't). But each has their strengths, the right tool for the right job.
- 0xTJ 1y agoSeeing "all built-in functions and operators are single unicode symbols" stood out to me, given that APL existed well before Unicode did. It's not that it's wrong today, but that wasn't always the case. My father used APL back in high school, and that was before the earliest year mentioned in the "History" section of the Unicode Wikipedia article.
- gitonthescene 1y agoIt wasn’t Unicode but it wasn’t ASCII either. I think here unicode is probably shorthand for not ASCII.
- WorldMaker 1y agoUnicode inherited most of APL's encoding sets from EBCDIC code pages. Almost no one would choose to work in EBCDIC today, so it is practical to just say Unicode as the last encoding left standing (for everyone not working on legacy APL code on [emulated] IBM mainframe hardware).
- xelxebar 1y ago> Array programming is similar to functional programming – the primary way to control execution involves composition of functions – but APL tends to encourage the reliance on global properties and sweeping operations rather than low-level recursion4. This AoC solution is, indeed, quite the functionista! Better yet, it leans heavily into point-free expressions. The style is pretty popular amongst APL language enthusiasts and puzzlers. That said, you actually see quite different APL styles in the wild: - Pointed declarative style, also a popular with functional programmers (e.g. anything like this[0] from the dfns workspace) - Imperative, structured programming, very common in legacy production systems (e.g. this[1] OpenAI API interface) - Object-oriented, also common in somewhat newer production environments (e.g. the HTTP interface[2]) - Data-parallel style (e.g. Co-dfns[3]) Heck, APL even has lexical and dynamic scope coexisting together. IMHO, it's truly underrated as a language innovator. [0]:https://dfns.dyalog.com/c_match.htm https://dfns.dyalog.com/c_match.htm [1]:https://github.com/Dyalog/OpenAI/blob/main/source/OpenAI.apln https://github.com/Dyalog/OpenAI/blob/main/source/OpenAI.apl... [2]:https://github.com/Dyalog/HttpCommand/blob/master/source/HttpCommand.dyalog https://github.com/Dyalog/HttpCommand/blob/master/source/Htt... [3]:https://github.com/Co-dfns/Co-dfns/blob/master/cmp/PS.apl https://github.com/Co-dfns/Co-dfns/blob/master/cmp/PS.apl
- librasteve 1y agothis is pretty cool i think the first raku (perl6) parser (pugs) was written in Haskell, certainly all the team learned Haskell before they started
- _glass 1y agoDone by Audrey Tang who later on became Minister of Digital Affairs of Taiwan.