## Do notation for monad in function returning a different type

haskell bind operator

maybe monad haskell

state monad

monad laws

haskell return

haskell io monad

haskell list monad

Is there a way to write `do`

notation for a monad in a function which the return type isn't of said monad?

I have a main function doing most of the logic of the code, supplemented by another function which does some calculations for it in the middle. The supplementary function might fail, which is why it is returning a `Maybe`

value. I'm looking to use the `do`

notation for the returned values in the main function. Giving a generic example:

-- does some computation to two Ints which might fail compute :: Int -> Int -> Maybe Int -- actual logic main :: Int -> Int -> Int main x y = do first <- compute x y second <- compute (x+2) (y+2) third <- compute (x+4) (y+4) -- does some Int calculation to first, second and third

What I intend is for `first`

, `second`

, and `third`

to have the actual `Int`

values, taken out of the `Maybe`

context, but doing the way above makes Haskell complain about not being able to match types of `Maybe Int`

with `Int`

.

Is there a way to do this? Or am I heading towards the wrong direction?

Pardon me if some terminology is wrongly used, I'm new to Haskell and still trying to wrap my head around everything.

**EDIT**

`main`

has to return an `Int`

, without being wrapped in `Maybe`

, as there is another part of the code using the result of `main`

as `Int`

. The results of a single `compute`

might fail, but they should collectively pass (i.e. at least one would pass) in `main`

, and what I'm looking for is a way to use `do`

notation to take them out of `Maybe`

, do some simple `Int`

calculations to them (e.g. possibly treating any `Nothing`

returned as `0`

), and return the final value as just `Int`

.

Well the signature is in essence wrong. The result should be a `Maybe Int`

:

main :: Int -> Int ->Maybe Intmain x y = do first <- compute x y second <- compute (x+2) (y+2) third <- compute (x+4) (y+4)return(first + second + third)

For example here we `return (first + second + third)`

, and the `return`

will wrap these in a `Just`

data constructor.

This is because your `do`

block, implicitly uses the `>>=`

of the `Monad Maybe`

, which is defined as:

instance Monad Maybe where Nothing >>=_ = Nothing (Just x) >>= f = f x return = Just

So that means that it will indeed "unpack" values out of a `Just`

data constructor, but in case a `Nothing`

comes out of it, then this means that the result of the entire `do`

block will be `Nothing`

.

This is more or less the convenience the `Monad Maybe`

offers: you can make computations as a chain of *succesful* actions, and in case one of these fails, the result will be `Nothing`

, otherwise it will be `Just result`

.

You can thus not at the end return an `Int`

instead of a `Maybe Int`

, since it is definitely possible - from the perspective of the types - that one or more computations *can* return a `Nothing`

.

You can however "post" process the result of the `do`

block, if you for example add a "default" value that will be used in case one of the computations is `Nothing`

, like:

import Data.Maybe(fromMaybe) main :: Int -> Int ->Intmain x y =fromMaybe 0$ do first <- compute x y second <- compute (x+2) (y+2) third <- compute (x+4) (y+4) return (first + second + third)

Here in case the `do`

-block thus returns a `Nothing`

, we replace it with `0`

(you can of course add another value in the ** fromMaybe :: a -> Maybe a -> a** as a value in case the computation "fails").

If you want to return the first element in a list of `Maybe`

s that is `Just`

, then you can use ** asum :: (Foldable t, Alternative f) => t (f a) -> f a**, so then you can write your

`main`

like:-- firstnon-failing computation import Data.Foldable(asum) import Data.Maybe(fromMaybe) main :: Int -> Int -> Int main x y = fromMaybe 0 $asum[ compute x y compute (x+2) (y+2) compute (x+4) (y+4) ]

Note that the `asum`

can still contain only `Nothing`

s, so you still need to do some post-processing.

**A Fistful of Monads,** We even saw how to map a function a -> b over other functions of type r -> a to get m a, how do you apply to it a function that takes a normal a and returns a We've already encountered do notation when we were doing I/O and there we In fact it is a Writer monad using the Builder type, and all you need is just the Builder monoid. Even more unfortunate, the applicative functors were introduced to Haskell's standard libraries only after monads and arrows, thus many types were instances of the Monad and Arrow classes, but not instances of Applicative.

Willem's answer is basically perfect, but just to really drive the point home, let's think about what would happen if you could write something that allows you to return an int.

So you have the `main`

function with type `Int -> Int -> Int`

, let's assume an implementation of your `compute`

function as follows:

compute :: Int -> Int -> Maybe Int compute a 0 = Nothing compute a b = Just (a `div` b)

Now this is basically a safe version of the integer division function `div :: Int -> Int -> Int`

that returns a `Nothing`

if the divisor is `0`

.

If you could write a main function as you like that returns an `Int`

, you'd be able to write the following:

unsafe :: Int unsafe = main 10 (-2)

This would make the `second <- compute ...`

fail and return a `Nothing`

but now you have to interpret your `Nothing`

as a number which is not good. It defeats the whole purpose of using `Maybe`

monad which captures failure safely. You can, of course, give a default value to `Nothing`

as Willem described, but that's not always appropriate.

More generally, when you're inside a `do`

block you should just think inside "the box" that is the monad and don't try to escape. In some cases like `Maybe`

you might be able to do `unMaybe`

with something like `fromMaybe`

or `maybe`

functions, but not in general.

**All About Monads,** There are as many different type of monads as there are strategies for combining computations, but there The return function puts a value into a monad container. Here is a sample of do notation using the Maybe monad: m a is a container holding a value of type a. The return function puts a value into a monad container. The >>= function takes the value from a monad container and passes it to a function to produce a monad container containing a new value, possibly of a different type.

I have two interpretations of your question, so to answer both of them:

##### Sum the `Maybe Int`

values that are `Just n`

to get an `Int`

To sum `Maybe Int`

s while throwing out `Nothing`

values, you can use `sum`

with `Data.Maybe.catMaybes :: [Maybe a] -> [a]`

to throw out `Nothing`

values from a list:

sum . catMaybes $ [compute x y, compute (x+2) (y+2), compute (x+4) (y+4)]

##### Get the first `Maybe Int`

value that's `Just n`

as an `Int`

To get the first non-`Nothing`

value, you can use `catMaybes`

combined with `listToMaybe :: [a] -> Maybe a`

to get `Just`

the first value if there is one or `Nothing`

if there isn't and `fromMaybe :: a -> Maybe a -> a`

to convert `Nothing`

to a default value:

fromMaybe 0 . listToMaybe . catMaybes $ [compute x y, compute (x+2) (y+2), compute (x+4) (y+4)]

If you're **guaranteed** to have at least one succeed, use `head`

instead:

head . catMaybes $ [compute x y, compute (x+2) (y+2), compute (x+4) (y+4)]

**Do notation considered harmful,** It contains the Put monad, which in principle has nothing to do with a a new function called void that makes ignoring of return values explicit: The first function that the Monad type class defines is return. It's the same as pure, only with a different name. Its type is (Monad m) => a -> m a. It takes a value and puts it in a minimal default context that still holds that value. In other words, it takes something and wraps it in a monad.

**Haskell/do notation,** result was of the type IO () , i.e. an empty value in the IO monad. This example will "return" the full name as a string inside the IO monad, which will be assigned to the variable "name" in our new function. The de-sugared version is simply a regular let expression where the in part is whatever follows from the do syntax. Returning values . The last statement in do notation is the overall result of the do block. In the previous example, the result was of the type IO (), i.e. an empty value in the IO monad.

**Monad (functional programming),** In functional programming, a monad is a design pattern that allows structuring programs return :: a -> M a (also called unit) which wraps any value of type a into a The do notation in haskell, for instance, allows to write monadic code blocks as function types s -> a from a common source s , is another canonical example Fail with a message. This operation is not part of the mathematical definition of a monad, but is invoked on pattern-match failure in a do expression. As part of the MonadFail proposal (MFP), this function is moved to its own class MonadFail (see Control.Monad.Fail for more details). The definition here will be removed in a future release.

**Lesson 31. Making Monads easier with do-notation,** Gxz do-notation rv ymspifil working with Monad a; Xalrtsnae ltxm Monad But the use of the Monad methods >>= , >> , and return quickly becomes cumbersome. as an echo function, using >>= is often easier than doing things with do-notation. This task should be similar to the types of problems you solved in unit 4. When using do-notation and a monad like State or IO programs look very much like programs written in an imperative language as each line contains a statement that can change the simulated global state of the program and optionally binds a (local) variable that can be used by the statements later in the code block.

##### Comments

- The point is that these calculations should result in a
`Maybe`

as well, or if not, you can use a`return`

. - Not sure what you're referring to,
`compute`

or`main`

? Either way,`compute`

already returns a`Maybe`

value, while`main`

is intended to definitely return an`Int`

, hence no`Maybe`

. In other words, one of the calculations in`main`

might fail, but at least one should pass which guarantees that`main`

has an`Int`

return value. - but the idea of a
`Monad Maybe`

is to see`Maybe`

s as "potentially failing" computations. So here you make a "chain" of potentially failing computations, and return`Just result`

in case it succeeds, and`Nothing`

otherwise. If you are sure`compute`

will always return an`Just _`

, then why does it have the signature`Int -> Int -> Maybe Int`

? - Thanks, your comment that refers to it as a chain of successful actions made it clearer to me, and I realize I actually am going in the wrong direction. What I intend is not for it to be a chain of actions, but a series of computations (which any might fail, but one is guaranteed to pass), and returning the first out of the series that passed. In essence, what
`main`

is doing is abstracting away the possible failures and choosing the first that succeeds, so that a definite`Int`

value can be used elsewhere when it calls`main`

. Is there a way to do this? - @lookarpthestars: you could use
`asum`

for that, like`asum [compute x y, compute (x+2) (y+2)]`

, which will return the first`Just`

in the list, but this is still a`Maybe`

, since it is possible that*all*computations fail. - See: hackage.haskell.org/package/base-4.12.0.0/docs/…
- Sweet, this comment along with the part you added after the edit gives me something to work from. Appreciate the concise answer.
- @lookarpthestars to your first comment,
*no*, main is*not*"choosing the first that succeeds". only if all three computations succeed it returns a Just (with the sum of three results). otherwise it returns Nothing. so it tries to run all of them (one after another, but*all*of them) and then combine all the results.