I was kinda surprised when I read the source code of instances of Applicative Complex
and Monad Complex
from GHC Data.Complex
module:
-- | @since 4.9.0.0
instance Applicative Complex where
pure a = a :+ a
f :+ g <*> a :+ b = f a :+ g b
liftA2 f (x :+ y) (a :+ b) = f x a :+ f y b
-- | @since 4.9.0.0
instance Monad Complex where
a :+ b >>= f = realPart (f a) :+ imagPart (f b)
What the...? The Applicative Complex
instance seems to treat complex numbers as just size-two arrays. And they both seem more like arrow operations. Is there any mathematical basis behind them? Either there is or not, what are they used for?
A functor is a data type that implements the Functor typeclass. An applicative is a data type that implements the Applicative typeclass. A monad is a data type that implements the Monad typeclass. A Maybe implements all three, so it is a functor, an applicative, and a monad.
Monads are simply a way to wrapping things and provide methods to do operations on the wrapped stuff without unwrapping it. For example, you can create a type to wrap another one, in Haskell: data Wrapped a = Wrap a. To wrap stuff we define return :: a -> Wrapped a return x = Wrap x.
monads are used to address the more general problem of computations (involving state, input/output, backtracking, ...) returning values: they do not solve any input/output-problems directly but rather provide an elegant and flexible abstraction of many solutions to related problems.
A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
Edited to add note at bottom re: "linear" package.
The instances were added as per this Trac 10609 ticket initiated by a mailing list post where Fumiaki Kinoshita noted that there were some missing instances in the base libraries that seemed to be definable in only one way and proposed a patch to add them.
As far as I can see, there was no mathematical motivation for adding them, though there's at least one mathematically meaningful operation that can be expressed applicatively, namely scalar multiplication:
> pure (*) <*> pure 2 <*> (3 :+ 4)
6 :+ 8
>
In a follow-up to the above mailing list post, Edward Kmett noted that he was in favor because he'd had to add orphan instances for Complex
to his linear
package for years to make up for the missing instances.
It looks like he found them useful in defining an Additive
instance for Complex
thus essentially making a Complex
a special case of a two dimensional vector.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With