samber / mo

🦄 Monads and popular FP abstractions, powered by Go 1.18+ Generics (Option, Result, Either...)
https://pkg.go.dev/github.com/samber/mo
MIT License
2.47k stars 80 forks source link

Either: Add Map helper function #7

Open CorentinClabaut opened 1 year ago

CorentinClabaut commented 1 year ago

closes #6

samber commented 1 year ago

Hi @CorentinClabaut

Why do you need a mo.Map() helper, instead of mo.Either[A, B].Match() ?

CorentinClabaut commented 1 year ago

It is to be able to map the either to a different type.

That's why I added an helper function instead of a new method.

CorentinClabaut commented 1 year ago

This helper would be helpful for cases like this:

type Authentification struct { mo.Either[BearerToken, BasicAuth] }

func (a Authentification) GetHeader() string {
        mo.Map(a,
        func(token BearerToken) string { return BuildBearerAuthHeader(string(token)) },
        func(cred BasicAuth) string { return BuildBasicAuthHeader(cred.Username, cred.Password)} })

So far what we can do is:

type Authentification struct { mo.Either[BearerToken, BasicAuth] }

func (a Authentification) GetHeader() string {
    if a.IsLeft() {
        return BuildBearerAuthHeader(string(a.MustLeft()))
    } else {
        basicAuth := a.MustRight()
        return BuildBasicAuthHeader(basicAuth.Username, basicAuth.Password)}
    } 
}

Which is less readable, more error prone.

samber commented 1 year ago

Hi @CorentinClabaut and sorry for the late reply.

I wonder if we could build a proper implementation of monads, with Applicative, Foldable, Traversable...

We must be able to run a Map() on any data structure of this repository.

Any idea how to do that? 🤔

CorentinClabaut commented 1 year ago

I can't think of a way of doing it with a single function.

What about creating multiple functions MapOption, MapResult, MapEitherX ?