Hi Haskell Cafe,
I'm finding that I really like type families. For instance, the GHC.List.lookup and Data.Map.lookup functions annoy me because their names clash, yet their type are so similar. With type families, I could define a more generic lookup function like this:
import Data.Map as MAP
import GHC.List as LIST
class MapType ma where
type Key ma
type Item ma
lookup :: Key ma -> ma -> Maybe (Item ma)
instance (Ord ka) => MapType (MAP.Map ka a) where
type Key (MAP.Map ka a) = ka
type Item (MAP.Map ka a) = a
lookup ka ma = MAP.lookup ka ma
instance (Eq ka) => MapType [(ka, a)] where
type Key [(ka, a)] = ka
type Item [(ka, a)] = a
lookup ka ma = LIST.lookup ka ma
This lookup function works on both "Map ka a" and "[(ka, a)]" types and I no longer need to qualify my lookup function with the module name.
The downside I suppose is that lookup is no longer a function that can be manipulated freely:
*Main> let x = lookup
*Main> let y = Fx.Data.Map.lookup
<interactive>:1:8:
Ambiguous type variable `ma' in the constraint:
`Fx.Data.Map.MapType ma'
arising from a use of `Fx.Data.Map.lookup' at <interactive>:1:8-25
Probable fix: add a type signature that fixes these type variable(s)
A shame that. I had been hoping it would be possible to have a generic lookup function that could be used in every way the current collection of various lookup functions can be used.
So much nicer if 'y' above could be bound to the Fx.Data.Map.lookup with the same type:
*Main> :t Fx.Data.Map.lookup
Fx.Data.Map.lookup :: forall ma.
(Fx.Data.Map.MapType ma) =>
Fx.Data.Map.Key ma -> ma -> Maybe (Fx.Data.Map.Item ma)
And then have the ambiguity resolve later when 'y' is actually used.
-John