Reputation: 2967
I've been given the following class interface:
class Misty m where
banana :: (a -> m b) -> m a -> m b
unicorn :: a -> m a
And now I'm required to modify this to enable:
jellybean :: (Misty m) => m (m a) -> m a
I believe the question is pushing me to add a subclass of Misty
, with multi parameters:
class Misty m => VeryMisty m a where
... banana' (Just (Just v)) = banana --?
I'm unsure how to create a function in Misty
to operate on this nested monad?
I'm also unsure whether my approach is correct and/or the simplest?
Upvotes: 1
Views: 77
Reputation: 6255
I think you don't have to extend the class, or add a subclass. Consider what the type signature of banana
looks like if you would pick m a
for the a
in the signature of banana
(the type variable a
can stand for any type, so also for m a
):
banana :: Misty m => (m a -> m b) -> m (m a) -> m b
Do you see that this already starts to look quite close to jellybean
? You only have to "get rid" of the first argument, and make b
to be the same as a
. The easiest way to achieve this would be to use the identity function id
:
jellybean :: (Misty m) => m (m a) -> m a
jellybean x = banana id x
A nice way to see the second step easier is that once you discover that you could use the first argument to jellybean
as the second of banana
is to use a typed hole:
jellybean :: (Misty m) => m (m a) -> m a
jellybean x = banana _ x
On loading this into the REPL, Haskell will print out:
Found hole `_' with type: m a -> m a
So you see what you'll need here to make this typecheck in this context.
Upvotes: 5