# Shapeless: Introduction and HLists (Part 1)

My good friends from Scalera asked me if I would want to write a post for them, and they made me an offer I couldn’t refuse, “We’ll get you a beer” they said… and here I am! I can’t say no to a good beer friend. This is the very first post I’ve ever written about Scala, so please bear with me.

## What is Shapeless?

Shapeless is a library created by Miles Sabin that aims to improve generic programming in Scala.

To achieve this it makes use of a bunch of macros and type level tricks, sometimes called whitchcraft, that push the language to its limits. There is a lot to talk about Shapeless, but in this first part we are going to focus on the basics, the most popular structure… yes, you’re right, we are talking about `HList``s!!!

## HLists

This is probably the most known feature of Shapeless, and the best start point (IMO) to tackle it, so let’s get started introducing what an `HList` is.

`HList` stands for Heterogeneous List, i.e. a list of elements of possibly different types. That’s it, the concept is real simple, the consecuences are far more interesting. This allows us to have a list containing a `String` and an `Int`. But you might be thinking… I can do that with a regular Scala `List`. Well, let’s take a look:

```scala> List("scalera", 3)
res0: List[Any] = List(scalera, 3)
```

Although it seems this is a `List` with two elements of different type, the fact is that from a type level point of view these two elements have the same type, `Any`. You can’t do anything useful with this `List`, in order to do so you must do some ugly castings here and there.

How do `HList`s solve this problem? Well, an `HList` stores the type of every element in the list. This way we know the type of the first element, the type of the second element, and so forth. Let’s try the same example we saw before, this time using an `HList`.

The syntax for creating an `HList` is the same as for creating a `List`, we just have to replace the constructor name:

```scala> HList("scalera", 3)
res0: shapeless.::[String,shapeless.::[Int,shapeless.HNil]] = scalera :: 3 :: HNil
```

The result type is a little bit confusing, but we can use infix notation to make it cleaner, the result type then would be `String :: Int :: HNil`. As you can see, we have all the types stored, we are not losing any info! Furthermore, we statically know the size of the list!

So we can say that `HList`s are more powerful than `List`s, and here is an example to prove it:

```val list: List[Any] = "John Doe" :: 26 :: Nil
val hlist: String :: Int :: HNil = "John Doe" :: 26 :: HNil

list.head.toUpperCase // error: value toUpperCase is not a member of Any
```

Notice you can use two different syntax in order to build `HList`s, similar to what you can do for regular `List`s:

```HList("scalera", 3) <===> "scalera" :: 3 :: HNil
List(1, 2, 3) <===> 1 :: 2 :: 3 :: Nil
```

Also, you can tell from the example above we have similar methods to work with `HList`s

```val hlist = 1 :: "two" :: 3 :: "four" :: HNil
hlist.tail // "two" :: 3 :: "four" :: HNil
hlist take 2 // 1 :: "two" :: HNil
```

So far we’ve seen that `HList`s have similarities with regular `List`s, being the formers more powerful, but besides `List`s, there are other Scala structures more similar to `HList`s. These structures are tuples and case classes.

All these three data structures(hlists, tuples and case classes) have the same shape, they can store the same information, and you can go from one to another without losing any information. Let’s see an example:

```case class User(name: String, age: Int)
type UserTuple = (String, Int)
type UserHList = String :: Int :: HNil

val user: User = User("John Doe", 26)
val userTuple: UserTuple = ("John Doe", 26)
val userHList: UserHList = "John Doe" :: 26 :: HNil

def fromUserToUserHList(user: User): UserHList = ???
def fromUserHListToUser(userHList: UserHList): User = ???
...
```

It would be straightforward to implement these functions and I encourage you to try to do so. It’s a good exercise to get used to `HList`s.

## Why would I use HLists then?

So, if an `HList` is very similar to a case class or a tuple, what’s the big deal? What can you do with an `HList` you can’t with a case class or tuple? Well, the big difference is that `HList`s are a more powerful abstraction, it abstracts over tuple arity for instance. You can’t write a method over tuples, because `Tuple2` and `Tuple3` are not related to each other, but you can create a method for `HList`s and run it with `HList`s of arbitrary size. This is out of the scope of this post though.

## Conclusions

We’ve seen that `HList`s are a powerful abstraction that provides us with the advantages of both lists and tuples. This is only the tip of the iceberg though, as its power really shines when we combined with other Shapeless type class, `Generic`. But we’ll leave it for another post…

# Shapeless: Introducción y HLists (Parte 1)

Mis buenos amigos de Scalera me preguntaron si quería escribir un post para el blog, y me hicieron una oferta que no pude rechazar, “Te invitamos a una cerveza” dijeron… ¡y aquí estoy! No puedo decir que no a una buena cerveza un buen amigo. Este es el primer post que escribo relacionado con Scala, así que tened paciencia conmigo.

## ¿Qué es Shapeless?

Shapeless es una librería creada por Miles Sabin, cuyo propósito es mejorar la programación genérica en Scala.

Para conseguirlo utiliza una serie de macros y técnicas avanzadas a nivel del sistema de tipos, que muchos simplemente llaman whitchcraft (brujería), que llevan al lenguaje al límite. Hay muchos temas que tratar cuando hablamos de Shapeless, pero en esta primera parte nos vamos a centrar en los principios básicos, la estructura más popular… sí, estás en lo cierto, ¡estoy hablando de las `HList`s!

## HLists

Esta es probablemente la característica más famosa de Shapeless, y el mejor punto de partida (en mi opinión) para empezar, así que comencemos introduciendo qué es una `HList`.

El nombre `HList` proviene de Heterogeneous List (listas heterogeneas), en otras palabras, una lista con elementos que pueden ser de distinto tipo. Eso es todo, el concepto es muy simple, pero las consecuencias son muy interesantes. Esto nos permite tener una lista formada por un `String` y un `Int` por ejemplo. Puede que estes pensando ahora mismo… Ya puedo hacer eso con una lista normal y corriente. Bueno, vamos a ver si es verdad:

```scala> List("scalera", 3)
res0: List[Any] = List(scalera, 3)
```

Aunque pueda parecer que esta lista tiene dos elementos de distinto tipo, la verdad es que desde el punto de vista del sistema de tipos estos dos elementos son del mismo tipo, `Any`. No se puede hacer nada útil con esta lista, si quisieras hacerlo tendrías que hacer algún que otro casting, con los peligros que eso conlleva…

¿Cómo solucionan este problema las `HList`? Pues muy sencillo, una `HList` guarda el tipo de todos y cada uno de los elementos que la componen. De esta manera sabemos que tipo tiene el primer elemento, el segundo, etc. Vamos a probar con el ejemplo anterior, esta vez utilizando una `HList`.

La sintaxis para crear una `HList` es la misma que para crear una `List`, sólo cambiaremos el nombre del constructor:

```scala> HList("scalera", 3)
res0: shapeless.::[String,shapeless.::[Int,shapeless.HNil]] = scalera :: 3 :: HNil
```

El tipo de retorno es un poco confuso, pero podemos utilizar notación infija para simplificarlo, el tipo de retorno quedaría `String :: Int :: HNil`. Como puedes ver, tenemos todos los tipos guardados, ¡No perdemos ninguna información! Es más, ¡Podemos saber estáticamente el tamaño de la lista!

Así pues, podemos decir que las `HList`s son más potentes con las `List`s estandar de Scala, y aquí hay un ejemplo para probarlo:

```val list: List[Any] = "John Doe" :: 26 :: Nil
val hlist: String :: Int :: HNil = "John Doe" :: 26 :: HNil
list.head.toUpperCase // error: value toUpperCase is not a member of Any
```

Como habrás podido ver, se pueden utilizar distintas sintaxis para construir una `HList`, al igual que para construir `List`s:

```HList("scalera", 3) <===> "scalera" :: 3 :: HNil
List(1, 2, 3) <===> 1 :: 2 :: 3 :: Nil
```

Además, puedes comprobar que muchos de los metodos definidos para `List`s se pueden utilizar también para `HList`s.

```val hlist = 1 :: "two" :: 3 :: "four" :: HNil
hlist.tail // "two" :: 3 :: "four" :: HNil
hlist take 2 // 1 :: "two" :: HNil
```

Hasta ahora hemos visto que `HList` tiene similaridades con `List`, siendo la primera más potente, pero a parte de `List`, hay otras estructuras en Scala que son más parecidas a `HList`. Estas estructuras son las tuplas y las case classes.

Estas tres estructuras (hlists, tuplas y case classes) tienen la misma forma, puden guardar la misma información, y se puede ir de una a la otra sin perdida de información. Veamos un ejemplo:

```case class User(name: String, age: Int)

type UserTuple = (String, Int)
type UserHList = String :: Int :: HNil

val user: User = User("John Doe", 26)
val userTuple: UserTuple = ("John Doe", 26)
val userHList: UserHList = "John Doe" :: 26 :: HNil

def fromUserToUserHList(user: User): UserHList = ???
def fromUserHListToUser(userHList: UserHList): User = ???

//...
```

Sería bastante directo implementar estas funciones, y te animo a que lo intentes. Es un buen ejercicio para tomar contacto con las `HList`s.

### ¿Por qué querría usar HList entonces?

Si una `HList` es muy parecida a una case class o una tupla, ¿Por qué son importantes? ¿Qué puedes hacer con una `HList` que no puedas hacer con una case class o una tupla? Pues bien, la gran diferencia es que `HList` es una abstracción más potente, abstrae sobre la aridad de las tuplas por ejemplo. No puedes escribir una función sobre tuplas, por que `Tuple2` y `Tuple3` no están relacionadas, sin embargo, puedes crear una función sobre `HList` y ejecutarla con `HList`s de tamaño arbitrario. Aunque esto queda fuera del ámbito de este post.

## Conclusiones

Hemos visto que `HList` es una abstracción muy potente que nos brinda las ventajas de las listas y las tuplas al mismo tiempo. Sin embargo, esto es solo la punta del iceberg, ya que su verdadero potencial sale a relucir cuando las combinamos con otra typeclass de Shapeless, `Generic`. Pero esto lo dejaremos para otro post…