Aren't accessor functions polymorphic?


#1

Hello,

I’m just learning Elm. I was curious about polymorphism, and I noted that functions can’t e polymorphic in Elm. Yet I also noticed these accessor functions.

Suppose I have some record type

stringThings = { concat = (\x y -> x ++ y) }
numThings = { concat = (\x y -> x + y ) }

.concat stringThings "foo" "bar" -- "foobar"
.concat numThings 2 3 -- 5

Here .concat looks like a polymorphic function. Just exploring this curiosity here.

Regards.


#2

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.


#3

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.