Paweł Stawicki — Senior Software Engineer

Scala implicits and their inequalities

Have you ever run into error with two conflicting implicit values in Scala? First, let’s recap what implicit parameters are. They are different from implicit conversions in Scala, but I’m not going to elaborate on it this time.

What is implicit parameter

Implicit parameter is a parameter that you don’t need to pass manually to a function, the compiler does it automatically. All it needs is to have an implicit parameter of a given type in scope. But what does “in scope” mean? Where can compiler get these parameters from? First, it looks in current scope, it means that if implicit value is declared in current class (where the method is called), or its trait, it’s going to be used. Next the compiler reaches to companion objects of the parameter type. If it is looking for implicit type F[T] , it looks both in companion object of F , and companion object of T . Moreover, it also looks in companion objects of super classes of F and T .

Implicit parameters conflict

Recently I run into a problem of 2 conflicting implicit parameters. Compiler found 2 implicit parameters of a given type and thrown an error. To boil the example to the simplest one, let’s first create simple trait, which is going to become implicit:

Now let’s create another type, TaggedType , so that our 2 types are more complicated and compiler can’t say which is simpler, and cannot resolve the conflict automatically.

Finally we can declare 2 implicit methods providing instances of Imp type:

When these methods are declared in the same place, on the same level (e.g. in the same trait) compiler reports an error and implicits conflict, when trying to generate implicit value e.g. of type Imp[TaggedType[Option[Int]]]

That’s because both method matches. It might not seem clear at first glance, there is Option after all, and only one method provides implicit with Option , doesn’t it? Well, not really. In case of the method with Option it is clear why it might be chosen. But in case of the another method, Option[Int] might be substituted for V , so it also matches.

Looking for match for Imp[TaggedType[Option[Int]]] :

def y[V]: Imp[TaggedType[V]] matches, because Option[Int] might be substituted for V

matches, because might be substituted for def x[V](…) : Imp[TaggedType[Option[V]]] also matches, because Int might be substituted for V .

In our case we needed both implicits, but the one with Option has higher priority, because we want to use it when possible, and the simple one only in other cases.

Solution

Solution is quite simple — it’s enough to put lower-priority implicit to some trait, and extend this trait. When compiler looks for implicits, it first checks the type’s companion object, and implicit found there has higher priority than the one in the trait that the object extends:

The clever compiler

Now why did we need TaggedType for this example? Without TaggedType compiler can recognise that Option[Int] is more complicated type than Int , and choses method x for generating the implicit. With TaggedType the types become:

TaggedType[Int] => Int with Tag[Int]

TaggedType[Option[Int]] => Option[Int] with Tag[Option[Int]]

and in such case compiler can’t recognise which type is simpler, both implicits have the same priority, and conflict occurs.

Marcin Baraniecki — Frontend Lion

I found multi-stage Docker builds really inspiring

Recently I’ve been tasked with preparing a Docker container for the front-end (React) app. It was required to:

build static assets (HTML/JS/CSS)

serve them via HTTP, avoiding tools like webpack-dev-server (not recommended in production environments) or other node.js-based servers (the less code the better)

define some advanced reverse-proxy logic for HTTP and WebSocket traffic

Building static assets in the React project could be easily achieved with node.js-based development tools. For the last two points, I decided to use nginx. Thus, I needed to use two tools (node.js & nginx) within one Docker container. As it turned out, multi-stage Docker builds were the answer. This invaluable article provided my with an idea for an end-to-end solution, which proved to fulfil all the requirements.

Dariusz Mydlarz — Software Engineer

I learned how to reduce Docker image size

Lately we were having a Node application and its Docker image grew up to

1.07 GB. It looked a bit suspicious, as the application was pretty simple.

Fortunately I came across Anton Fisher’s article that helped me to reduce the size to 399 MB — by 73% less than the original.

How did I do it? I made two changes in our Docker file.

I changed node:10 image to node:10-alpine . Which is almost bare Linux that is much lighter than original one. It forced me to install required dependencies (like gcc, python, git), but the gain was worth it. I excluded test directory from compilation to the target output — (cause we use TypeScript underneath).

With these two little changes I’ve made it possible to significantly reduce the image size and we all lived happily ever after!

I recommend this tool

In the last month I have upgraded my cooperation with a terminal.Here are couple of things I’ve made.

First — I’ve generated idea command from IntelliJ — as shown in the picture below. This way I can type idea. in the directory I’m interested in and… boom! It is being opened by Idea. How I could even work without that before?!

Menu to generate “idea” command line tool.

Other improvements to my terminal are:

k — for listing directories with their git status — https://github.com/supercrabtree/k

— for listing directories with their git status — https://github.com/supercrabtree/k bat — cat with syntax highlighting — https://github.com/sharkdp/bat

— cat with syntax highlighting — https://github.com/sharkdp/bat zsh-autocompletion — for completing commands (like fish shell) — used for a while but worth mentioning — https://github.com/zsh-users/zsh-autosuggestions

— for completing commands (like fish shell) — used for a while but worth mentioning — https://github.com/zsh-users/zsh-autosuggestions fzf — command line fuzzy finder — for easier repeating history commands — https://github.com/junegunn/fzf

I have also came up with simple and powerful aliases adding.

Easy aliases adding flow

I’m spending a lot of time in terminal. While features like fuzzy search or autocompletion from previous paragraphs are great, there is always a room for improvement. For me this improvement means using aliases. While there are a lot of aliases built into zsh (git rocks!), there are always custom things that I want to have.

I have created a simple bash function addallias that allows me to quickly add new aliases. Just like that:

How does it look like? It is very simple:

As you can see, I am storing aliases in separate file, which is even automatically sent to cloud (magic!). In my zshrc file I just load that file with source command.

Now, every time I see typing a command is becoming more often and more painful, I can easily add aliases and make my work smoother.

What are your best tips to work with terminal? Let us know in the comments. Best!