Stream: ideas

Topic: automatic eta-expansion, to rename polymorphic f'ns


view this post on Zulip jan kili (Jan 23 2025 at 23:55):

Currently, it seems that the only types that can't be renamed/aliased are polymorphic functions. foo = bar yields unexpected behavior if bar is a function with any type variables involved, like bar : List a -> a. foo's type will be determined by its first application, like foo ["x"] making it foo : List Str -> Str.

Since I like renaming functions in service of self-documenting code, I propose that the glorious compiler contributors implement Richard's suggestion (below) of the compiler performing "automatic eta-expansion", which is apparently the replacement of values with explicit lambdas when the value is implicitly a (polymorphic?) function. I have no idea if that sounds super hard and/or super blocked by other work - I just want to create this topic for discussion of its merits and hopefully lead to another thing that Just Works!

(I hope I'm summarizing everything accurately, since I'm weak on polymorphism and ignorant on lambda calculus.)

Here's a filtered view of the motivation and idea:

JanCVanB said:

I expect this to work, but it seems to be bugged. Is this actually intended behavior?

main! = \_ ->
    foo = mappy [1, 2, 3, 4] Num.toStr
    bar = mappy [" a", "b "] Str.trim
    ...

mappy = rename List.map
rename = \anything -> anything

...

Brendan Hansknecht said:

I'm pretty sure it should just work. It also should just work without the rename function just mappy = List.msp

JanCVanB said:

Glad to hear! Yeah mappy = List.map doesn't work either, which seems like a better starting point for debugging. (I do want the two-step version too.)

Ayaz Hafiz said:

yes, this is intended behavior

you need to wrap mappy in an explicit lambda for it to be polymorphic

eg mappy = \l, f -> List.map l f

everything that's not explicitly a function (syntactically) is not polymorphic. Everything that is not explicitly a function gets at most one type, and that type is determined by the first usage

Richard Feldman said:

wasn't this one of the situations where we could relax that if desired?

Ayaz Hafiz said:

it can be relaxed if you perform eta-expansion

i.e. write any value v of type a -> b to \a -> (v) a

Richard Feldman said:

I think we should do this

it's surprising that it doesn't work, and then the workaround is to do eta-expansion manually, so seems like a good thing for the compiler to do for you automatically

Ayaz Hafiz said:

[...] i dont see an issue with eta expansion

view this post on Zulip Sam Mohr (Jan 24 2025 at 00:52):

I'm here for this change. It shouldn't be that hard to implement, but it will require someone to understand the type system well enough to implement it. Could you create an intermediate-level GitHub issue for this?

view this post on Zulip Brendan Hansknecht (Jan 24 2025 at 02:32):

Yeah, I think we can greenlight just turning this into an issue. There isn't really a downside to adding this.


Last updated: Jun 16 2026 at 16:19 UTC