**Pagini **

# Workshops

**Parteneri**

Monads, baby!

Today we look at certain kinds of computations from a truly functional perspective:

- computations that might or might not have a value
- computations that might fail
- computations that will finish at some point

But we won't get into math and category theory for this.

We'll see what a monad is from a programming perspective, directly in the Scala language.

You can find today's contents here.

Let's implement some of our own monads.

- Let's write a monad equivalent with
`Option`

. Let's call this`Maybe`

, as in Haskell.- create a trait
`Maybe[+A]`

(remember the`[A]`

is equivalent to Java's`<A>`

syntax for generics and ignore the + for now) - add some functional primitives as methods to
`Maybe`

:- the monad requirements:
`map`

,`flatMap`

,`filter`

`zipWith`

, which receives a`Maybe[B]`

and returns a`Maybe[(A,B)]`

The signature is just a tiny bit more complex:

def zipWith[B](other: Maybe[B]): Maybe[(A,B)]

If either

`this`

or`other`

is empty, the result will be an empty`Maybe`

.`exists`

, which receives a predicate (a function of A to Boolean) and returns true if this instance contains an element which satisfies the predicate`orElse`

, a special method for`Maybe`

, which returns this instance if it's not empty, or an alternative otherwise; the signature will be

def orElse[B >: A](alternative: Maybe[B]): Maybe[B]

(ignore the

`>:`

for now)

How can you*delay*the computation of the alternative until you actually need it? (hint: call by value/call by name)

- add some utility methods to the
`Maybe`

trait:`isEmpty`

`toList`

`size`

- create two case subclasses:
`Just[A]`

and`Empty`

and implement the methods- what is
`Empty`

, actually? a case class? a case object? - methods should be quick to write and probably take two lines of code, at most

- An equivalent to Scala's
`Try`

monad, call this`Attempt[A]`

.- as before, create a trait
`Attempt[A]`

and two case subclasses,`Success[A]`

and`Fail`

`Success`

has a member of type`A`

, Fail has a member of type`Throwable`

- add some functional primitives to your
`Attempt`

and implement them in the subclasses:`map`

,`flatMap`

,`filter`

`zipWith`

`exists`

`isEmpty`

,`toList`

,`size`

- a special method -
`recoverWith`

; the method returns an alternative`Attempt`

computation if this one fails

- Talk about the Future[T] (pun intended) if you finish early!