Typeclassopedia presents the following exercise:
Implement pure and (<*>) in terms of unit and (**), and vice versa.
Here's Monoidal
and MyApplicative
:
class Functor f => Monoidal f where
u :: f () -- using `u` rather than `unit`
dotdot :: f a -> f b -> f (a,b) -- using instead of `(**)`
class Functor f => MyApplicative f where
p :: a -> f a -- using instead of `pure`
apply :: f (a -> b) -> f a -> f b -- using instead of `(<**>)`
First, let me show the Maybe
-like data type:
data Option a = Some a
| None deriving Show
Then, I defined instance MyApplicative Option
:
instance MyApplicative Option where
p = Some
apply None _ = None
apply _ None = None
apply (Some g) f = fmap g f
Finally, my attempt at implementing Monoidal Option
in terms of p
and apply
of MyApplicative
:
instance Monoidal Option where
u = p ()
dotdot None _ = None
dotdot _ None = None
dotdot (Some x) (Some y) = Some id <*> Some (x, y)
Is this right? My implementation of dotdot
with apply
doesn't seem
instance Monoidal Option where
u = p ()
dotdot None _ = None
dotdot _ None = None
dotdot (Some x) (Some y) = apply (Some id) (Some (x, y))
In particular, I'm curious about how to properly implement dotdot :: f a -> f b -> f (a, b)
with Applicative's (<*>)
- in my case it's apply
.