 Last time we implemented `Maybe`. Our example was a simple folding through user input lines. With `Maybe` it makes less sense, because `Maybe` is able to capture only “value or nothing”. The real value would be to conserve wrong user inputs, but still ignore them in a fold. That’s the place where we can use an `Either` data type.

## What is an Either?

An `Either` can `Left value` or `Right value` (again stolen from my Haskell experiences). It can be either `A` value or `B` value, but their type can be different, and usually they are different, otherwise we don’t have to `Either`.

An easy example would be an `Either String Int` where `Left` has `string` type, while `Right` has `int` type.

## Let’s implement an Either

``````// Either data type
type Either[L any, R any] struct {
left  L
right R

isRight bool
}

// Left value.
func (e Either[L, R]) Left() L {
return e.left
}

// Right value.
func (e Either[L, R]) Right() R {
return e.right
}

// IsRight check if it was a Right value.
func (e Either[L, R]) IsRight() bool {
return e.isRight
}

// Left creates a new Either with Left value.
func Left[L any, R any](value L) Either[L, R] {
return Either[L, R]{left: value}
}

// Right creates a new Either with Right value.
func Right[L any, R any](value R) Either[L, R] {
return Either[L, R]{right: value, isRight: true}
}
``````

The two extra helper function is there to make it easier to create an `Either` instance.

## How can we use it?

Let’s the same example we have from `Maybe`, but now when we use `Foldl` we log entries we skipped.

First we need a function that reads the “user input” and returns with channel of `Either`s.

``````import "github.com/yitsushi/go1-18-experiments/pkg/data"

func readFromUser() chan data.Either[string, int] {
ch := make(chan data.Either[string, int])

myList := []data.Either[string, int]{
data.Right[string](12),
data.Right[string](2),
data.Left[string,int]("asd"),
data.Right[string](8),
}

go func() {
for _, v := range myList {
ch <- v
}

close(ch)
}()

return ch
}
``````

Not much changed, we replaced all `Just()` calls with `Right()`, and all `Nothing()` calls with `Left()`.

Our folding function will be a bit different. Previously we used the same kind for folding. We used a `chan Maybe` and a `Maybe` as the final result. Now we have a `chan Either`, but we have no reason to return with an `Either`. We could return with a single `int` value, but what if all the input values are wrong (`Left`)? We can return with a `Maybe`:

``````import (
"constraints"
"fmt"
"log"

"github.com/yitsushi/go1-18-experiments/pkg/data"
)

func add[L any, R constraints.Ordered](c data.Maybe[R], value data.Either[L, R]) data.Maybe[R] {
if !value.IsRight() {
log.Printf("Skip: %s\n", value.Left())

return c
}

if c.IsNothing() {
return data.Just(value.Right())
}

return data.Just(c.Value() + value.Right())
}

func main() {
result := data.FoldlIter(
data.Nothing[int](),
Basically, if we see a `Left` value, we skip the value, log the original value and return with our carry value without changes. If it was a `Nothing` it will remain `Nothing`. If we had `Nothing` in our carry value and we have a `Right` value, just return with the new value. Otherwise, add the two values together and return with a `Just` value.