2
votes

I started on my first, simple web app in Elm. Most of my code is currently adapted from https://github.com/rtfeldman/elm-spa-example. I am working against a API that will give me a authToken in the response header. I have a AuthToken type that is supposed to represent that token. Taking the value out of the header and converting it to a result that's either a error String or a AuthToken is causing trouble. I expected that I could just say I am returning a AuthToken, return a String and it would be fine because my AuthTokens right now are just Strings. It seems like there clearly is something about Elm types I am not understanding.

Here is the definition of AuthToken:

type AuthToken
  = AuthToken String

and my way too complicated function that for now just tries to do some type changes (later I want to also do work on the body in here):

authTokenFromHeader : String -> Http.Response String -> Result String AuthToken
authTokenFromHeader name resp =
    let
        header = extractHeader name resp
    in
    case header of
        Ok header ->
            let
                token : Result String AuthToken
                token = Ok (AuthToken header)
            in
            token
        Err error -> Err error

I expected the happy case would return a Ok result with the string from the response header converted to a AuthToken as its value. Instead I am getting Cannot find variable 'AuthToken'. From the documentation I expected to get a constructor with the same name as the type. If I just use Ok header, the compiler is unhappy because I am returning Result String String instead of the promised Result String AuthToken.

What's the right approach here?

1
just to be sure that AuthToken is visible, do you have type AuthToken definition in the same file or have it exposed from some imported module? - Igor Drozdov
@IgorDrozdov is right, you should expose the type constructor in the module where you define AuthToken module X.AuthToken exposing (AuthToken(..)) and also where you import the module import X.AuthToken exposing (AuthToken(..)). Side remark: what's also confusing (although not incorrect) is that you define header twice (once as Result in the let binding and once as a String in your case pattern) - monk

1 Answers

4
votes

The code looks fine as is. The error message indicates that type AuthToken has been defined in a different module and not imported completely to the module that defines authTokenFromHeader. You can read about Elm's module system in the Elm guide: Modules.

A possible fix, assuming that type AuthToken is defined in module Types, and authTokenFromHeader is defined in module Net, is:

Types.elm:

module Types exposing (AuthToken(..))

type AuthToken = AuthToken String

Net.elm:

module Net exposing (authTokenFromHeader)

import Types exposing (AuthToken(..))

authTokenFromHeader : String -> Http.Response String -> Result String AuthToken
authTokenFromHeader name resp =
    ...

Note the use of AuthToken(..) instead of just AuthToken, which ensures that the type as well as the type constructors are imported/exported.

Or just move the definition of type AuthToken into the same file as the definition of authTokenFromHeader.