So when you say a function can not be polymorphic, do you mean function overloading (also known as ad hoc polymorphism)?

Something like redeclaring a function multiple times with different type signatures:

```
concat : String -> String -> String
concat x y = x ++ y
concat : Int -> Int -> Int
concat x y = x + y
```

This is not possible in Elm.

You can however do parametric polymorphism (generic functions, template programming) in Elm. Your example of the `.concat`

function uses parametric polymorphism.

The type signature of this accessor function looks like this:

```
.concat : { a | concat : b } -> b
```

which means: the function `.concat`

takes an extensible record that must have a field called `concat`

(it can also have other fields). It will return the value of that field, no matter the type.

“If you give me a record with the field `concat`

that has the type `String`

, I will give you the `String`

. If it has the type `Int`

, I will give you the `Int`

. I actually don’t care what the type is, I will just give you the value.”

Many functions actually uses parametric polymorphism. If a type signature says `a`

, `b`

, or any lowercase type variable it is polymorphic on parameters.

This would be a simple example of parametric polymorphism:

```
fn x = x
```

Here it is easy to see that it does not really matter what type `x`

is, since the function doesn’t do anything with it. Just returns it unaltered. The type signature would be `fn : a -> a`

. This function is called the identity function.

Check List.map for example. It is polymorphic (actually most List functions are).

```
map : (a -> b) -> List a -> List b
```

"Give me a function from type `a`

to type `b`

. Then give me a List of `a`

and I will give you back a List of `b`

. `a`

and `b`

can be any types. They can also be the same type, the List.map function does not care what types they are.