Haskell in Termux in Android 10 in LG Q60

So I decided to bite the bullet and learn Haskell.

I am VERY late to learn Haskell. Other languages have incorporated pretty much every useful Haskell feature and I used most of them already. Anything I learn from this will probably be purely philosophical.

Since it will be purely philosophical, I don’t want to do this while sitting at a desk, but rather on my pocket supercomputer that I keep on my person at all times. 

My phone (a humble LGQ60 with Android 10) already has Termux in it. Termux is a terminal emulator that runs on Android.  It is a package manager and Bash interpreter that connects to the internet. I have successfully used it for small scale C/C++, JS and Python development.

If you are going to install Termux just for this tutorial, run “pkg update” in it before you do anything else and update the core libs.

The official way of managing Haskell toolchain is GHCup. You get it and the rest of the toolchain by curling a script. Alas, it didn’t work for me.

I decided to get an older version from the package manager itself, which installed nicely enough. It did crash immediately with a segfault upon execution though. So, this also didn’t work for me.

So I looked around the internet and found a Termux-specific build of a much older interpreter called HUGS. It is small enough that I can compile it from sourcecode, which means I can deal with problems locally on the phone itself. (see above: I already have gcc and make)

I saw the following instructions in the readme file:

$ termux-chroot
$ mkdir src
$ cd src
$ git clone https://github.com/trenttobler/android-termux-hugs.git
$ cd android-termux-hugs
$ make install

Do I really need root to run a secondary interpreter? I went ahead and did it anyway and found that binaries are saved under /usr/local/(bin|lib) folders. I can’t access them without root, since they don’t belong to my personal user, which is bad for doing stuff on a phone. I think I can just change the build script and do it without root privileges. I went ahead and edited the relevant path names in the Make files.

As you can see I use VIM in a shell on a phone to edit a makefile.

Next time all that crap will be dumped into a folder under my home directory ( henceforth referred to tersely as “~”)

I went ahead and moved all build artifacts to new locations manually – no need to compile all that code again right now.

$ cd /usr/local
$ cp bin/* ~/local/bin/.
$ cp -r lib/. ~/local/lib/.

I may delete the originals later if everything works out fine without root.

Now I forgot to take a screenshot but I also learned that the lib folder has to be directly under ~/   OR you should change the HUGS path to ~/local/ in HUGS config. Also don’t forget to add ~/local/bin/ to your bash PATH variable. You should finally refresh the PATH variable to use it in the running session. I just restarted the app.

Type hugs in prompt to start the REPL.

If you do what HUGS says and execute 😕 in the REPL, you will see a list of available commands.

So HUGS seems to have a :cd command for changing directory but no command for printing out where you are OR listing out what’s in the folder. 🤦

I’ll need to fix this. Hum the tune of ‘sound of silence’ as you read on.

hello darkness my old friend
I’ve come to write c code again
because some core feature is missing
shells without fs apis are annoying
and the vision that is planted in my brain
still remains
whispered in the sound of posix compliance

I go back to the github repo where I found this to read the source code.

First lets see where :cd is implemented. By performing a dumb string search in the github repo I find it immediately.

Well hello there…

It seems if I am on __SYMBIAN32__ I can use pwd, but not on Termux?
This isn’t even funny; why would this only work on symbian?

For those who are not old enough: Symbian was an embedded phone firmware for the pre-iPhone era.

The printDir() is a super thin wrapper for the OS api…

So I decided to take stock of what this file additionally does and noticed this.
This looks promising. Would a function called shell escape let me use shell commands in REPL?

So a quick google search found me this.

Shell escape :![command]

A :!cmd command can be used to execute the system command cmd without leaving the Hugs interpreter. For example, :!ls (or :!dir on DOS machines) can be used to list the contents of the current directory. For convenience, the :! command can be abbreviated to a single ! character.

from offical docs

Why isn’t this explained in the help text in the first place? I went and looked at the source code for the help text. It’s not even maliciously hidden; it just doesn’t exist.

OK I don’t need to write C with system calls. I can just use ! to get what I want. !pwd and !ls just work.

🎉 CRISIS AVERTED 🎉

Since it will probably work, I will go and read http://learnyouahaskell.com/

 If I figure out a good way of explaining what a monad is I’ll write a new blog about it.

A UML diagram is a map

A UML diagram is a map.

A map is a simplified representation of complicated or hard to observe reality. A map should be simple enough to be digestible, yet it should also contain enough information to be useful for decision-making.

The current oldest surviving map is from Bronze age. It is a piece of rock that depicts the region where it was found. (click here for a diagram) It is obviously the kind of map you draw to take stock of things. To keep things under record. It doesn’t cover a large enough area to be useful for planning movement.

The oldest known maps that show not only where the cartographer lived, but also included territories of trade partners and potential military targets are from the roman empire. Based on our knowledge of how roman empire functioned it is safe to assume that they were actively used for planning.

Correlation does not mean causation, but I still think there is something to be said about how the “where are we standing?” map is older than the “where are we going?” map. It makes intuitive sense to determine where you are before you plot a course to some other place. If your imaginary path has a

Mind you, this distinction is entirely subjective. Both are maps in the exact same way, the only difference is the intention of the user.

Now it should be apparent where I am going with this in terms of UML diagrams.

Waterfall people originally intended UML to be a planning tool and a programming language. An expensive software engineer would design the system with UML then cheaper coders would write source code (probably in C++) according to UML. This two tiered workflow proved to be cumbersome.

UML is a human to human protocol. And THOSE are open to all sorts of corruption. If a programmer is being threatened with being fired on the spot, they will absolutely not care about the correctness of UML in a hypothetical future. Suchh practical constraints frequently cause operators to sideline UML and directly change source code. In time UML turns into stale documentation.

Most programmers have experienced the “stale documentation” version of UML and developed knee jerk reactions against anyone who comes bearing UML tools. But in doing so also miss an opportunity.

Remember, a map does not have to indicate where you are going, it is also useful if it shows you where you are. So lets assume we change the intention behind why we use UML. There are multiple tools that will read your code and create an UML diagram from it. Wouldn’t it be useful to have a single page overview of all your classes? As long as you don’t take it too seriously it will be fine.