Skip to content

Explicit namespace type import can bring a value into scope

As an example, recall that Data.Functor.Product exports

data Product f g a = Pair (f a) (g a)

It seems that importing Data.Functor.Product ( Product ( type Pair ) ) imports both the data constructor Pair (a value) as well as its promotion:

ghci> :seti -XExplicitNamespaces -XDataKinds
ghci>
ghci> import Data.Functor.Product ( Product ( type Pair ) )
ghci>
ghci> :type Pair
Pair
  :: forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
     f a -> g a -> Product f g a
ghci>
ghci> :kind Pair
Pair :: forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
        f a -> g a -> Product f g a

This seems a bit odd: if I'm explicitly asking for the type Pair, shouldn't I only get the promoted data constructor, and not the value? This is an example of a type import bringing in a value into scope, which seems odd.

The users' guide isn't very clear about this, but it says that type is a disambiguation mechanism more than anything else, so if the item is unambiguous then it doesn't change the behaviour, so that in the above example import Data.Functor.Product ( Product ( type Pair ) ) is equivalent to import Data.Functor.Product ( Product ( Pair ) ).

In the same vein, we have:

ghci> :seti -XExplicitNamespaces -XDataKinds -XPatternSynonyms
ghci>
ghci> import Data.Functor.Product ( pattern Pair )
ghci>
ghci> :type Pair
Pair
  :: forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
     f a -> g a -> Product f g a
ghci>
ghci> :kind Pair
Pair :: forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
        f a -> g a -> Product f g a

In this case we have a pattern import bringing in a type into scope. I suppose the same reasoning holds as above.

Edited by sheaf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information