2

Is it possible to construct a function that will map of a tuple of monads of arbitrary arity?

E.g.,

f :: (m a -> m [a]) -> (m x, m y) -> (m [x], m [y])

(but for arbitrary arity). This similar question, has a number of promising suggestions; e.g., lens' each or over both, but each seem to require a tuple of homogenous types: I want to use a tuple of homogenous monads with differing inner types.

Community
  • 1
  • 1
user3416536
  • 1,429
  • 9
  • 20

1 Answers1

4

It's not possible in the way that you're saying.

In your type signature, the initial function can only take an m a, but you expect to pass it an m x and an m y, so the types don't match.

It's certainly possible to do it with rankNTypes enabled:

{-# LANGUAGE rankNTypes #-}
f :: Monad m => (forall a. m a -> m [a]) -> (m x, m y) -> (m [x], m [y])
f fun (x, y) = (fun x, fun y)

This is because forall a. inside the brackets forces it to be polymorphic, rather than just for a type a.


What you're probably wanting is something like this:

f :: Monad m => (a -> m b) -> (m a, m a) -> (m b, m b)

or even

f :: Monad m => (a -> m c) -> (b -> m d) -> (m a, m b) -> (m c, m d)

Note that I changed the function type from m a -> m b to a -> m b because that allows us to sequence monadic actions, rather than transform the monad, which makes more sense when we want to manipulate them.

chi
  • 111,837
  • 3
  • 133
  • 218
AJF
  • 11,767
  • 2
  • 37
  • 64
  • 1
    Okay, thanks @AJFarmer. I feared it couldn't be done, but couldn't explicitly reason why; so figured it's worth asking, if only to clarify why not. The key seems to be that the fn passed as first arg is pinned down to a single specific a at instantiation time, unless we use rankNTypes as you say. – user3416536 Apr 12 '15 at 10:50
  • @user3416536 that's right; type variables are carried across a function's type, and it's not implicit that two types with different variables are equal, but it's possible. `forall` just says that it can work on any type, which, of course, includes `m x` and `m y`! – AJF Apr 12 '15 at 11:19