Skip to content

Conversation

@gusty
Copy link
Member

@gusty gusty commented Jun 10, 2025

This was described here #623

@gusty gusty marked this pull request as ready for review June 10, 2025 20:46
@gusty gusty merged commit b237216 into master Jun 12, 2025
4 checks passed

// Compile tests

let inline mapOfGroup (key: 'T -> 'Key when 'Key : equality) (sequence: '``Collection<'T>``) : Map<'Key, '``Collection<'T>``> =
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fxdmhtt this function is kind of useful.

I already thought about grouping in the past and realized that ideally they should return non-empty collections.
Returning a map makes sense for the eager groupBy (as opposed to the lazy chunkBy), so maybe we should create an issue to discuss a function that groups into a NonEmptyMap.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand how this works.

Why can I write the correct type signature by simply making the Id redundant?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, when I was writing the secondary encapsulation library, I encountered many situations where I had to delete the type signature to compile. But I thought it was caused by my weak F# ability, so I didn't report it to you.

Can you tell me what happened?

@gusty
Copy link
Member Author

gusty commented Jun 13, 2025

Why can I write the correct type signature by simply making the Id redundant?

@fxdmhtt F# type inference is quite complicated when combined with overload resolution. It has a complex tie breaker algorithm that, in the middle of solving type equations attempts to find a single overload that makes more sense than the others, if that's not the case, it does more type solving before attempting again. That's why sometimes we need to create ambiguity by adding a second overload with the same kind of properties (arities, struct-ness, etc) in order to create the necessary ambiguity to prevent the tie breaker to resolve earlier to a specific overload which will take the whole type solving nowhere.

Of course, the F# compiler could be improved to make this situation smarter, but it's not a trivial change.

In fact, when I was writing the secondary encapsulation library, I encountered many situations where I had to delete the type signature to compile. But I thought it was caused by my weak F# ability, so I didn't report it to you.

Can you tell me what happened?

Similar situations are encountered when your code contains type annotations, they force the compiler to take a different path and sometimes they make things worse, so believe it or not there are cases when working with those generic functions where you should let the compiler do his work.

Having said this, I hope you understand that taking the type inference to the limits is not always a desirable situation, this library contains functions which should be used carefully (or not used at all), I mean the use of generic functions, especially when combined have to be really justified to overcome the type inference drawbacks. Otherwise the Extension module has lot of "normal" functions that can be used instead.

@fxdmhtt
Copy link
Contributor

fxdmhtt commented Jun 13, 2025

So the root cause is the defects of F# itself, and we just use some "magic" to circumvent these defects.

Then there is another problem: if the function signature does not have a complete type description, the API documentation and fsi files are not very standardized. If the function has a complete type description, in order to circumvent the defects of F# itself, it may be necessary to modify the underlying reference library, but this is generally impossible.

It seems that the ceiling of F# is a bit low.

@gusty
Copy link
Member Author

gusty commented Jun 13, 2025

Yes, while many people have expressed desire to have type classes in F#, I personally think that it won't change that much the current situation, but instead F# type system needs to support Higher Kinds. That would solve lot of issues and make the type system more consistent.
I'm pretty much sure one day we'll see Higher Kinds in .NET
What I'm not sure is whether I will be retired by that time.

@fxdmhtt
Copy link
Contributor

fxdmhtt commented Jun 13, 2025

If F# is willing to support HKT, it will be closer to Haskell.

That is the classic question: Why didn't Microsoft directly introduce Haskell into .NET?

So I don't think I will see that day.

To be honest, I feel that Microsoft is letting F# run wild.

@wallymathieu
Copy link
Member

HKT would probably not give you Haskell on .net. There are many features in Haskell...

@gusty
Copy link
Member Author

gusty commented Jun 13, 2025

Starting with the lazy evaluation by default.
But Haskell and HKTs are not the same thing. Other languages support HKTs, which are maybe closer to F#.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants