1

I have 2 type definitions

type Mapper a k v = a -> [(k,v)]
type MapperM m a k v = a -> m [(k,v)]

I want to write a function that convert a value from type

(Ord k, Monad m) => MapperM m a k v

to type

Ord k => Mapper a k v 

basically a function that takes a -> m [(k,v)] as an argument and return a -> [(k,v)] as output.

All my attempts are failing with the Haskell type checks.

Tomer
  • 1,159
  • 7
  • 15
  • 3
    Perhaps [this QA](https://stackoverflow.com/a/8567831/2550406) is useful to you? Especially [this comment](https://stackoverflow.com/questions/8567743/how-to-extract-value-from-monadic-action#comment10622826_8567743) – lucidbrot Feb 29 '20 at 10:45
  • 3
    You can’t do this, since it is impossible in general to convert `m a` to `a` for an arbitrary monad `m`. (This is just what @lucidbrot linked to, but I thought it might be useful to restate this here so you don’t have to follow a link.) – bradrn Feb 29 '20 at 10:49
  • Is it possible that my output will be (Monad m) => m Mapper a k v - basically wrap with Monad my impossible original desired output ? – Tomer Feb 29 '20 at 10:57
  • @GilShafriri So you mean something like `(Ord k, Monad m) => MapperM m a k v -> m (Mapper a k v)`? This would also be impossible: you would have to be able to convert a function `Monad m => a -> m b` to `Monad m => m (a -> b)`, which cannot be done. (This time, it’s impossible because any monadic side-effects in `a -> m b` can depend on `a`, whereas any monadic side-effects in `m (a -> b)` cannot depend on `a`.) – bradrn Feb 29 '20 at 11:01
  • 3
    If you have a function `Monad m => a -> m [(k,v)]` you *can* convert that to `a -> [(k,v)]` with the following `convert = (runIdentity .)` (you might have to import from `Data.Functor.Identity`). The issue arises when the monad is a *specific* monad, in which case you cannot necessarily convert. But if the function is generic over *any* monad, you can use the identity monad. – oisdk Feb 29 '20 at 13:34

1 Answers1

3

I believe it is mathematically impossible.

Consider the case when m is Maybe: the function could return [(k,v)] from Just [(k,v)], but what would it return from Nothing?

If the monad is IO, extracting the argument from the monad would break the safety that IO provides.

Also consider that your function would have to work for any conceivable monad.

Alistair Wall
  • 332
  • 1
  • 2
  • 3