Babra Cunningham
Babra Cunningham

Reputation: 2967

Generic nested monad manipulation?

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

Answers (1)

Rüdiger Hanke
Rüdiger Hanke

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

Related Questions