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

Transforming return type when using map #66

Open
Luviz opened this issue Mar 5, 2025 · 5 comments
Open

Transforming return type when using map #66

Luviz opened this issue Mar 5, 2025 · 5 comments

Comments

@Luviz
Copy link

Luviz commented Mar 5, 2025

Hi I have been looking to use this package in my solution however every time I have tried to so I feel like something is missing.

In our solution we want to use Options and Results every time we are uncertain of the return value.

I do use monads in python and node (typescript) and it's great there is a a lot that we can do with elegantly, and I do like MarshalJSON function that you have implemented.

My issue with mo is that when we need to map a type to another type, see example below.

this code is more like a pseudocode

type UserRequestForm struct {
	Email     string
	FirstName string
	LastName  string
	Address   string // can be empty
	Title     string // can be empty
}

type User struct {
	Id        string // uuid/guid
	Email     string
	Name      string
	FirstName string
	LastName  string
	Address   string // can be empty
	Title     string // can be empty
}

func (data UserRequestForm) TDO() User {
	return User{
		Id:        uuidx.NewV4().String(),
		Email:     data.Email,
		Name:      fmt.Sprintf("%v %v", data.FirstName, data.LastName),
		FirstName: data.FirstName,
		LastName:  data.LastName,
		Address:   data.Address,
		Title:     data.Title,
	}
}

func UserRequestFormToDTO(value UserRequestForm) mo.Option[User] {
	return mo.Some(value.TDO())
}

Here I want to get a option of UserRequestForm and if it has a value I wan't to convert it to a TDO and push it to a DB.

So something looking like this:

func CreateUser(user mo.Option[UserRequestForm]) error {
	return user.FlatMap(UserRequestFormToDTO).Match(
		func(value User) {
			db.CreateUser(value) // Value should be of type User
		},
		func() (error) {
			return fmt.Errorf("Form data could to be converted to User database object ")
		})
}

I'm kind new to GO thereby I might be a bit ignorerat, so there might be that writing something like the code above is might not be a good idea.
However I know that there is good support generics and type inference in GO. So I don't see any issues with creating functions looking like this:

func Map[T any, R any](value T, callback func(T) R) R {
	return callback(value)
}

func main() {
       u := Map(data, UserRequestFormToDTO) // typeof u is User
}

Here is my question, is there a reson why the Map and FlatMap function is hard code as generic. Or is just that you haven't implemented support for it yet, and in that case can I try to make PR?

@axaluss
Copy link

axaluss commented Mar 10, 2025

this is needed badly

@Luviz
Copy link
Author

Luviz commented Mar 11, 2025

I found som commented out code ./options/transforms.go.

I looks like someone tried it but gave up.

@axaluss
Copy link

axaluss commented Mar 11, 2025 via email

@Luviz
Copy link
Author

Luviz commented Mar 11, 2025

We could always fork it and make the change. @samber haven't responded and if you were able to find a workaround, I would love to check it out and see we could use it as well.
Also I could help as well if it's needed.

@axaluss
Copy link

axaluss commented Mar 11, 2025

I'm using Result a lot. The code can be copied and adapted for any of the mo types.
I'm considering moving to https://github.com/IBM/fp-go because it's way more feature complete ...but looks more complicated than need be what i'm going for....

func FlatMap[T any, V any](
	result mo.Result[T],
	f func(T) mo.Result[V],
) mo.Result[V] {
	v, err := result.Get()
	if err != nil {
		return mo.Err[V](err)
	}
	return f(v)
}

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

2 participants