Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mapWithKey does not allow the resulting map to be of different type #162

Open
cies opened this issue Apr 4, 2018 · 4 comments
Open

mapWithKey does not allow the resulting map to be of different type #162

cies opened this issue Apr 4, 2018 · 4 comments

Comments

@cies
Copy link

cies commented Apr 4, 2018

This errors out:

:set -XTypeFamilies
:set -XNoImplicitPrelude
:set -XFlexibleContexts
:set -XOverloadedStrings
:m ClassyPrelude
let m = mapFromList ([("a", 1), ("b", 2)] :: [(Text, Int)])
mapWithKey (\k v -> k ++ tshow v) m

And it seems obvious why:

:t mapWithKey

Outputs:

mapWithKey :: IsMap map =>
     (ContainerKey map -> MapValue map -> MapValue map) -> map -> map

So it can only map to exactly the same type of map. Very much what I'm not expecting from a map function in a higher-kinded language. Which would be:

map :: Functor f => (a -> b) -> f a -> f b

Allowing me (but obviously not forcing me) to change the type of map with mapping.

Is this restriction really needed? And, if yes, how do I get around it?

I'm now going the mapToList, processing, and then back with mapFromList, route.

I really like classy-prelude and all it brings me: thanks a lot for open source'ing and maintaining it!

@snoyberg
Copy link
Owner

snoyberg commented Apr 4, 2018 via email

@cies
Copy link
Author

cies commented Apr 4, 2018

Thanks for the apt response. If /you/ have no idea how to generalize this, then I give up right here. Maybe a small note in the docs that this does not behave as one might expect from a map function (it's more like an updateEach) as "the monomorphic nature of the typeclasses disallows a more general approach" is all I can think of.

Feel free to close, I'm fine with the mapToList-mapFromList approach.

@snoyberg
Copy link
Owner

snoyberg commented Apr 4, 2018 via email

@sniperrifle2004
Copy link
Contributor

I don't know if it is an appropriate solution, but PolyMap (being polymorphic) could have such a function if it had an associated key type:

type PolyMapKey map

pmapWithKey ::  (PolyMapKey map -> v1 -> v2) -> map v1 -> map v2

Without it is also possible, but you would have to rely on SetContainer's ContainerKey:

pmapWithKey :: (SetContainer (map v1), SetContainer (map v2),
      (ContainerKey (map v1)) ~ (ContainerKey (map v2)))
      => (ContainerKey (map v1) -> v1 -> v2)
      -> map v1 -> map v2

Which seems a bit to restrictive to me, but it does work for all current instances of PolyMap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants