What does `exposing (..)` mean in Elm?

exposing (..) allows you to call all the functions in the package directly.

For example, if SamplePackage had the functions x and y, import SamplePackage would let you call SamplePackage.x and SamplePackage.y, while import SamplePackage exposing (..) would let you call x and y without specifying their containing package.

Note that import SamplePackage exposing (x) would let you call x directly, but you would still need to call y with SamplePackage.y. Likewise, import SamplePackage exposing (x, y) would let you call x and y, but not any other functions in the package.


This is an old question, but I'll answer anyway with another way to think of exposing (..), and explain a little about why it's usually a bad idea. If you have a background in Python programming, then you can think of this as like from module import * in Python. This Elm code:

import Graphics.Element exposing (Element, show)

would look like this in Python:

from Graphics.Element import Element, show

whereas this Elm code:

import Graphics.Element exposing (..)

would look like this in Python:

from Graphics.Element import *

The first two will only add the names Element and show to your current module's namespace; the latter two examples will add all the names from Graphics.Element to your namespace. This is convenient when you're first writing your module, as you might not know yet what names you're going to need from Graphics.Element. But once you've finished writing your module, it's wise to go back and change exposing (..) to exposing (just, the, names, you, need). That way you can be sure of not having any name collisions later.

For an example of how name collisions could be bad, say you write a module called myGraphics, in which you create a function called rotatedImage, because it's not (currently) in Graphics.Element. But later on, Graphics.Element adds a rotatedImage function, with subtly different semantics (e.g., your function used degrees, but the "official" function used radians). Now there are two rotatedImage functions that your code has available... and you could easily trip yourself up:

{- someOtherModule.elm -}
import Graphics.Element exposing (..)

{- ... more code ... -}
someImage = rotatedImage (pi / 2) sourceImage  -- Angle is in radians

Now you need a different function from your myGraphics module, so you import it:

{- someOtherModule.elm -}
import Graphics.Element exposing (..)
import myGraphics exposing (..)

{- ... more code ... -}
someImage = rotatedImage (pi / 2) sourceImage  -- WHOOPS, angle is now in degrees!

And suddenly the rotation of someImage has changed! When you imported myGraphics, did you intend for it to change how someImage looked on your page? Almost certainly not.

That's why import Foo exposing (..) should be avoided once your code is relatively stable. It's very useful in development, since you don't have to constantly be going back to the top of your code to add another name to your import statement. But once you've finished doing heavy development on your module and you're only making occasional changes to it, you should really switch to using import Foo exposing (just, the, names, you, need). You'll dodge many traps that way.


It means that you can access everything directly within the Graphics.Element module, without specifying the package first. Since this example only uses "show" and "Element", you could change the import line to:

import Graphics.Element exposing (Element, show)

And it will still work for this example.

Tags:

Elm