Hi people. Say I'm implementing a `Monad`

for an `F[_]`

, but want to override the `ap`

so that my `F[_]`

retains some parallel behaviour (for instance, using Matryoshka's `hyloM`

to perform some validation whilst building a tree). Am I utterly wrong ? I know that `Monad`

has laws, `Applicative`

has laws, but is there a formal law that says "thou shall never override" ?

(I'm asking because the library I need to feed a monad does provide an alternative method asking for a `Parallel`

)

@Baccata you can override whatever you want as long as it passes the laws :) It's being done all the time whenever your data type can provide more efficient implementation

@Baccata there is a law that ap is the same as you would get from pure and flatMap semantically. But it may be possible to optimize in some cases while keep semantic equivalence.

Okay, that's helpful :smile: . @johnynek Is that law implemented somewhere ?

Yes. In cats test for MonadLaws. I’m on the phone but you should be able to find it.

You can actualy use

`cats-laws`

module to add those laws to your test suites
here you have example how to use it:

https://github.com/monix/monix/blob/master/monix-eval/shared/src/test/scala/monix/eval/TypeClassLawsForTaskSuite.scala

https://github.com/monix/monix/blob/master/monix-eval/shared/src/test/scala/monix/eval/TypeClassLawsForTaskSuite.scala

@Avasil mmm I guess I see. Because

`map`

is implemented using `flatMap`

, override `ap`

could break the `Applicative`

laws
Is that why no

`Monad`

implementation is provided for `Validated`

?
I think so, with

`Monad`

you sequence effects and fail early but with just `Applicative`

you can evaluate effects independently and that's what you want for `Validated`

@Baccata

`Monad`

can't be implemented for `Validated`

because you cannot have a monad instance that accumulates errors (try writing one to see what I mean!), you can only short circuit, which would make `ap`

and `flatMap`

behave differently
@SystemFw yeah that's pretty obvious. My question had more to do with why

`ap`

and `flatMap`

behaving differently is bad I guess.
it's simply to allow refactors like this to be safe

```
for {
a <- fa
b <- fb
} yield f(a, b)
```

into`(fa, fb).mapN(f)`

right

thanks, that's the best explanation I've read about it ^^

And that’s even more important if you have some generic code that’s parametrized on

`F[_]: Monad`

and you decide you no longer need `Monad`

and simply change it to `Applicative`

, that’d change behaviour even though your code looks the same
Applicative on its own cannot enforce ordering of effects, you need a Monad constraints for that. But if you do have such a constraint, then Applicative ops are guaranteed to be consistent with the Monadic ones