serokell / universum

:milky_way: Prelude written in @Serokell
MIT License
176 stars 28 forks source link

Add 'ToPairs' type family with the ability to have list of pairs #97

Closed chshersh closed 6 years ago

chshersh commented 6 years ago

Currently toList for key-value containers returns list of values only:

ghci> :t toList @(HashMap _ _)
toList @(HashMap _ _) :: HashMap t1 t -> [t]

I think it might be more useful to return list of (key, value). This can be implemented as default here:

https://github.com/serokell/universum/blob/83330399969f99cd2afca739f1ffb1c75abd6d2d/src/Universum/Container/Class.hs#L92-L94

Like this for example:

type family ElementDefault (t :: *) :: * where
    ElementDefault (m k v) = (k, v)
    ElementDefault (f a)   = a

But this immediately will break behavior of all Foldable-like functions. Maybe this change is too radical...

neongreen commented 6 years ago

This is very bad because it would break any code which uses toList as a synonym for elems, and in many cases it will do so silently. It will also break elem :: Element a -> a -> Bool.

Either create toPairs or just deprecate toList and instead add keys, elems, pairs.

chshersh commented 6 years ago

@neongreen Yeah, one more thing is breaking something like:

maximum :: Ord (Element t) => t -> Element t

which doesn't make much sense... Solution with toPairs sounds better to me as well. Also, in that case we will be closer to Prelude interface thus less surprises to users.

So do you propose the following interface?

class ToPairs t where
    type Key t :: *
    type Val t :: *

    toPairs :: t -> [(Key t, Val t)]
    keys    :: t -> [Key t]
    elems   :: t -> [Val t]  -- maybe `vals` or `values`?