Koterpillar

GHC.Generics talk

Slides from the YOW! Lambda Jam 2017 about GHC.Generics.

Name levels

At first, programs have objects from the problem domain - be it Song, Fruit or House.

Of course, you need abstractions - Object, Model, Class (and perhaps Metaclass) or Message. The customers aren't interested in these, but they are real words at least.

And when that is not enough, enter concepts named after publication authors: Kan extension, Yoneda lemma and Lie group. They don't have corresponding words in the language, so perhaps even the authors don't have hopes of their wide usage.

P.S. Of course, you can just name your types K1 and M1.

Review: Working Effectively with Legacy Code

Thanks to the library of the company I work in for the ability to request books. "Working Effectively" is more than 10 years old, but the title looked promising.

In essense, all the book advocates is divide (the code into separate pieces), write tests and conquer (make changes). Perhaps about 70% is devoted to the ways of how to achieve that, with examples in Java. So knowledge of Java or at least the OO paradigm is a must before reading (and C and C++ desirable).

Of course, in the time being the programming languages and tools have changed, and it was interesting to compare whether the described techniques are now simpler, obsolete or new ones are needed.

On one hand, Java, being a statically typed language with rather strict decisions, makes one resort to building a complex web of interfaces, overridden methods and objects in the hard cases. To my knowledge, it now has tools that allow circumventing the inheritance, method visibility and other restrictions when testing. But it isn't worthwile in all cases - improving the code structure, even just to run the tests, is beneficial for changes later.

I won't discuss the C++ examples at all, because all they are is cheating on the compiler and linker. A lot of places use macros - I wonder if the author ever got a project where the macros themselves needed testing? However, good to read for the general knowledge.

The place where I envy the author is reliance on the compile stage errors. Thanks to the strict typing, practically the only place where a runtime error is possible is the implicit float to int conversion, and this is pointed out several times in different chapters. On the other hand, the author is heavily exploiting null, suggesting passing if an object of the needed type can't be constructed and hope it works.

There are no higher order functions in the book - perhaps Java didn't have delegates at the time. In C++, of course, one can make callable objects and even custom method tables, but, again, doing it just for testing is an overkill.

An interesting technique I saw that doesn't depend on particular language or paradigm is "scratch refactoring". Having saved the current state in a version control system, you start changing everything you can, however you want, paying no attention to the tests. If the changes touch several areas, that's still fine, continue as you please. And when there is finally a satisfactory result... remove all the changes, revert to the saved version and start again, with tests. The refactoring itself won't advance very far, but the experiment will give you an understanding of the direction to take.

One more note is about the architecture. Very often its understanding is different between team members, especially if the project has an architect detached from the real life. For this not to happen, the author suggests periodically explaining the system or its components' functionality, assuming no prior knowledge, in a limited number of sentences. Thus all the participants get an idealized version of the architecture, and subconsiously strive to support and enhance it instead of making random changes. I wonder whether these idealized descriptions can go into the modules' documentation, or it is worthwile making the team members make them up from scratch every time?

The last thing I want to point out is that the author focuses on writing unit tests. There is a good criterion for them - they are the tests that can run faster than 0.1 seconds. This resolves the contradiction in the "testing in isolation" definition - it's obvious that the + operator, when it is used in the tested method, doesn't need a mock, but an external service call, like a database, and similar must be excluded. It is a pity that Django, for example, practically imposes the reverse approach, where there are extensive tools for using ORM when testing and almost none for replacing it.

General recommendation: for working with object-oriented code, worth a read. Techniques specific to a particular language can be leafed through.

HackerX Melbourne

I've got an invitation to HackerX. I didn't think it was particularly worthwhile after I've got a repeat notification seeing as I didn't register on the first one, but decided to check it out. By the way, I don't know where did they get my address from - during the registration I was asked for LinkedIn and GitHub so perhaps not from there.

The event itself was crowded. Perhaps 50 people in the room, and that's considering a lot of name tags didn't get picked up. About 15 companies, the only familiar name was Telstra.

But that's not the main thing. During the registration they let me choose my programming languages, asked about GitHub and LinkedIn, but after the introduction they just let everyone take a spot at one of the employers' desks at will (5 minutes to a company). So, as I understand it, there was no matching of companies to developers based on interest - just a career fair.

Best REPL

What's 1 + 2? Let's ask Elm:

---- elm-repl 0.17.1 -----------------------------------------------------------
 :help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------------------------------------------------
> 1+2
Error: The following HTTP request failed.
<http://package.elm-lang.org/all-packages?elm-package-version=0.17.1&since=2016-10-24%2008%3A52%3A34.764973%20UTC>

FailedConnectionException2 "package.elm-lang.org" 80 False getAddrInfo: does not exist (Name or service not known)

The most interesting result of any REPL I've ever seen. Will try to convince the workplace to use it.

XMonad via Stack

XMonad can be installed via Stackage. But it's not enough to install, it needs to compile the user configuration - xmonad.hs. Being installed through stack install, XMonad tries to call the system GHC, which expectedly can't find the required libraries.

Ideally, XMonad could understand that it's installed through Stack, and called the corresponding compiler. There are precedents - HLint, for example, loads the required libraries for checking the code if it finds stack.yaml. But meanwhile it can be done manually.

XMonad calls GHC to compile the configuration, so one must first point to it from a wrapper script ~/bin/xmonad:

#!/bin/sh
export PREVPATH=$PATH
GHC_PACKAGE_PATH=$(stack exec env | grep GHC_PACKAGE_PATH | sed s/.\\+=//g 2>/dev/null)
export GHC_PACKAGE_PATH
PATH=$(stack exec env | grep ^PATH | sed s/.\\+=//g 2>/dev/null)
export PATH
exec $HOME/.local/bin/xmonad "$@"

This script has to be put in a directory preceding the one used by Stack - ~/.local/bin - in $PATH.

Now XMonad will call GHC installed through Stack, compile the configuration and launch the result. But all the other programs launched from within it will inherit the same settings, which confuses, among others, Stack itself. To fix this, we need to reinstate the system settings after the launch. Thus, in xmonad.hs:

main = do
    unsetEnv "GHC_PACKAGE_PATH"
    getEnv "PREVPATH" >>= setEnv "PATH"
    unsetEnv "PREVPATH"
    -- ...

The full configuration can be found in my repository:

Update

XMonad 0.13, or any version with e159ec3, supports a custom user build script that should make most of the above unnecessary.

Wintergatan

I liked what Kraftwerk did in the start of their career: unique, custom made instruments producing sound that wasn't heard before. Clips and concerts where you couldn't tell real people from robots. But 40 years passed, synthesizers and computers are used by more people than know what those mean, and Kraftwerk, unfortunately, have done nothing new.

Enter Wintergatan: Marble Machine, Starmachine2000 and SommarfÄgel. It's not a perfec comparison, but here it is, new sound and self-made instruments. No grandiose ideas yet, but let's see what comes next...

Arch Linux on MeegoPad

I wanted to replace a Raspberry Pi as a media center with something more powerful, so that the video and the UI doesn't stutter. So I found an Intel Compute Stick clone - MeegoPad T5.

For the impatient: still isn't working properly, but maybe someone else can figure something out.

Booting Linux

Surprise number one: it's a 64-bit platform with 32-bit UEFI. To boot from the standard Arch image, put a 32-bit GRUB next to the 64-bit systemd-boot EFI loader already there (or any other loader which can pass parameters to the kernel) and choose it through the UEFI Shell (F7 during startup shows the boot menu).

Wi-Fi module isn't visible during installation, see below - I had an Android phone acting as an access point.

The installation itself is going fine - 64-bit GRUB can install a 32-bit version of itself. But the booting of the installed system stops at:

Loading Linux ...
Loading initial ramdisk ...

Here's what helped me:

  • Remove load_video from grub.conf. It's not enough (?) to edit /etc/default/grub, had to remove it from /etc/grub.d/10_linux.
  • Turn off Quiet Boot and Fast Boot in BIOS.

Wi-Fi

The Wi-Fi module is a Realtek RTL8723BS. It is detected and started when rtl8723bs-dkms-git is installed from AUR (also see package comments there). Unfortunately the connection isn't stable and after some time stops working entirely. Applying the recommended patches from the driver page didn't help.

Time

(See update below.)

Despite the awful Wi-Fi transfer speed, ping results were looking interesting:

PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=50 time=0.00 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=50 time=0.00 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=50 time=0.00 ms
...

Turns out time on MeegoPad is passing... strangely (lanmei in this example):

$ while sleep 1; do echo "Local: $(date) Lanmei: $(ssh lanmei date)"; done
Local: Sun Jan 31 19:37:53 AEDT 2016 Lanmei: Sun Jan 31 19:36:17 AEDT 2016
Local: Sun Jan 31 19:37:54 AEDT 2016 Lanmei: Sun Jan 31 19:36:17 AEDT 2016
Local: Sun Jan 31 19:37:56 AEDT 2016 Lanmei: Sun Jan 31 19:36:17 AEDT 2016
Local: Sun Jan 31 19:37:57 AEDT 2016 Lanmei: Sun Jan 31 19:36:18 AEDT 2016
Local: Sun Jan 31 19:37:59 AEDT 2016 Lanmei: Sun Jan 31 19:36:18 AEDT 2016
Local: Sun Jan 31 19:38:00 AEDT 2016 Lanmei: Sun Jan 31 19:36:18 AEDT 2016
Local: Sun Jan 31 19:38:01 AEDT 2016 Lanmei: Sun Jan 31 19:36:18 AEDT 2016
Local: Sun Jan 31 19:38:03 AEDT 2016 Lanmei: Sun Jan 31 19:36:19 AEDT 2016
Local: Sun Jan 31 19:38:04 AEDT 2016 Lanmei: Sun Jan 31 19:36:19 AEDT 2016
Local: Sun Jan 31 19:38:05 AEDT 2016 Lanmei: Sun Jan 31 19:36:19 AEDT 2016
Local: Sun Jan 31 19:38:07 AEDT 2016 Lanmei: Sun Jan 31 19:36:19 AEDT 2016
Local: Sun Jan 31 19:38:08 AEDT 2016 Lanmei: Sun Jan 31 19:36:20 AEDT 2016
Local: Sun Jan 31 19:38:10 AEDT 2016 Lanmei: Sun Jan 31 19:36:20 AEDT 2016
Local: Sun Jan 31 19:38:11 AEDT 2016 Lanmei: Sun Jan 31 19:36:20 AEDT 2016
Local: Sun Jan 31 19:38:12 AEDT 2016 Lanmei: Sun Jan 31 19:36:21 AEDT 2016
Local: Sun Jan 31 19:38:14 AEDT 2016 Lanmei: Sun Jan 31 19:36:21 AEDT 2016
Local: Sun Jan 31 19:38:15 AEDT 2016 Lanmei: Sun Jan 31 19:36:21 AEDT 2016
Local: Sun Jan 31 19:38:16 AEDT 2016 Lanmei: Sun Jan 31 19:36:21 AEDT 2016
Local: Sun Jan 31 19:38:18 AEDT 2016 Lanmei: Sun Jan 31 19:36:22 AEDT 2016
Local: Sun Jan 31 19:38:19 AEDT 2016 Lanmei: Sun Jan 31 19:36:22 AEDT 2016
Local: Sun Jan 31 19:38:20 AEDT 2016 Lanmei: Sun Jan 31 19:36:22 AEDT 2016
Local: Sun Jan 31 19:38:22 AEDT 2016 Lanmei: Sun Jan 31 19:36:22 AEDT 2016
Local: Sun Jan 31 19:38:23 AEDT 2016 Lanmei: Sun Jan 31 19:36:23 AEDT 2016
Local: Sun Jan 31 19:38:25 AEDT 2016 Lanmei: Sun Jan 31 19:36:23 AEDT 2016
Local: Sun Jan 31 19:38:26 AEDT 2016 Lanmei: Sun Jan 31 19:36:23 AEDT 2016
Local: Sun Jan 31 19:38:27 AEDT 2016 Lanmei: Sun Jan 31 19:36:23 AEDT 2016
Local: Sun Jan 31 19:38:29 AEDT 2016 Lanmei: Sun Jan 31 19:38:29 AEDT 2016
Local: Sun Jan 31 19:38:30 AEDT 2016 Lanmei: Sun Jan 31 19:38:29 AEDT 2016
Local: Sun Jan 31 19:38:31 AEDT 2016 Lanmei: Sun Jan 31 19:38:29 AEDT 2016
Local: Sun Jan 31 19:38:33 AEDT 2016 Lanmei: Sun Jan 31 19:38:29 AEDT 2016
Local: Sun Jan 31 19:38:34 AEDT 2016 Lanmei: Sun Jan 31 19:38:30 AEDT 2016
Local: Sun Jan 31 19:38:35 AEDT 2016 Lanmei: Sun Jan 31 19:38:30 AEDT 2016

The two minute jump near the end is systemd-timesyncd discovering (how?) that something is wrong and synchronizing via NTP.

Conclusion

  • HDMI, X11, hardware acceleration work.
  • Built-in Wi-Fi is no good.
  • Kodi, which was the target of it all, plays video with continuous stuttering.

Update

The time problem was caused by the kernel patches from RTL8723BS driver. Vanilla kernel keeps the time fine.

PLIBMTTBHGATY

Since long I have a book queue (a topic for some other time) but now there's also one for languages I want to learn. So as soon as I saw a meetup for PLIBMTTBHGATY ("programming languages I've been meaning to try but haven't got around to yet") I didn't hesitate a bit.

It didn't fail the expectations: was very nice learning Rust (tough choice but more on that later) together with others. I was lucky to have someone already proficient in it nearby explaining the non-obvious moments. It's a pity I didn't have time to try something real, only got through the official tutorial and a bit of another.

Waiting for the next time! There are a lot of candidates - Elm, Agda and the likes (this time there was a person trying to do printf in Idris), even React.

It would be nice if after the end of the meetup someone from each table would summarise the interesting parts and rough edges they encountered. Would also help to either find the tutorial or a task beforehand or find someone already knowing the language to help. Going to prepare better the next time.

Transport cards

I have a little hobby - collecting transport cards from different places. Before it happened naturally, but now there are three helpful things that simplify things for a lot of people, but mean a hard time for my collection.

  • A card bought in any metro in Japan can be used in any other city. Same in Korea.
  • No one likes garbage, so one-time tickets are eaten by the validators at the end of the trip. Guangzhou has plastic tokens for that purpose - with RFID! They have to be touched on at the start of the trip and inserted in the end.
  • Lastly, paying by bank cards (London, Moscow). Ideal solution: there's no special card, but its function is performed.

Very convenient for everyone, but you have to actually collect the cards on purpose now...

P.S. One more convenience: selling special tourist cards in the airports. Fortunately, these are often not as useful as normal ones so can be safely ignored.