Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function list/find-maybe is a duplicate of list/foreach-while #583

Open
chtenb opened this issue Oct 5, 2024 · 6 comments
Open

Function list/find-maybe is a duplicate of list/foreach-while #583

chtenb opened this issue Oct 5, 2024 · 6 comments

Comments

@chtenb
Copy link
Contributor

chtenb commented Oct 5, 2024

pub fun find-maybe( xs : list<a>, pred : a -> e maybe<b> ) : e maybe<b>
pub fun foreach-while( xs : list<a>, action : (a) -> e maybe<b> ) : e maybe<b>

I think we can remove find-maybe from the standard library?

@daanx
Copy link
Member

daanx commented Oct 5, 2024

Ha, good catch. Mm, I think it was done this way as I was considering having a different datatype for the while family of actions:

type while<a> 
   Continue
   Break( result : a )

but I didn't follow up on this. It does feel a bit weird to look for an element in a list with foreach-while, like

[1,2,3].find-maybe(fn(i) if (i>=3) then Just(i) else Nothing)

vs

[1,2,3].foreach-while(fn(i) if (i>=3) then Break(i) else Continue)

not sure.

@chtenb
Copy link
Contributor Author

chtenb commented Oct 6, 2024

Interesting. The Break/Continue vocabulary is very charming.

What are your thoughts on having different isomorphic types in the core library, like maybe and while?
So continuing on your example, the foreach-while function would then return a while<a> value.
Suppose I would like to transform it to an a value by supplying some default value, I would want to call the fun default( m : maybe<a>, nothing : a ) : a on it. However, that function is defined for maybe types, not for while types.
We could duplicate all functions on maybe to work for while values, but that has a clear downside in code complexity.

Why do want to distinguish between isomorphic types at all? I think because we like to use this in domain modelling, such that code becomes more readable, and to make it more difficult to make mistakes related to mixing up values that conceptually represent different things.
One could argue that the core library does not do domain modelling, but exists to provide a programmer with a good set of basic operations. To this end, interoperability (i.e. making things possible) is perhaps more important than segmentation (i.e. forbidding things).

On the other hand, perhaps it's not a big deal, as long as there exist conversion functions between isomorphic types?

@chtenb
Copy link
Contributor Author

chtenb commented Oct 6, 2024

It does feel a bit weird to look for an element in a list with foreach-while

This is probably different for everyone. For me that was a natural way of using it. I was looking through the module for an iteration function that would allow some form of conditionality, such that I could pick a first element that would satisfy a condition. Something with while in the name sounds familiar and logical to reach for. It was only later that I found the find-maybe version and noticed that it did the same thing.
I also think that foreach-while sounds more general than find-maybe.

@zephyrtronium
Copy link

However, that function is defined for maybe types, not for while types. We could duplicate all functions on maybe to work for while values, but that has a clear downside in code complexity.

FWIW, I would say fun while/maybe(a: while<a>): maybe<a> solves this problem much more compactly.

@chtenb
Copy link
Contributor Author

chtenb commented Oct 7, 2024

Yes, that is what I alluded to in the last sentence. But note that if maybe is the canonical representation of its isomorphism class, and all the utility functions are defined on maybe, you will always have to call this conversion function to do something with the result of foreach-while, save explicit pattern matching.

@TimWhiting
Copy link
Collaborator

It would be interesting to have functional inheritance as a feature of datatypes.

i.e.

type maybe<a>
 ....

type while<a> inheriting (while/maybe)
   Continue
   Break( result : a )

fun while/maybe(a: while<a>): maybe<a>
   ...

Essentially the idea is, first implicit resolution attempts to find based on while, and then if it cannot find it, also tries maybe using the implicit coercion. Coercions could be automatically generated for isomorphic types (by request).

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

No branches or pull requests

4 participants