Command Line Arguments in Elm

Our first example demonstrates how to work with command-line arguments in Elm. Command-line arguments are a common way to parameterize execution of programs.

module Main exposing (main)

import Platform exposing (Program)
import Process
import Task exposing (Task)

type alias Model =
    { args : List String
    }

type Msg
    = NoOp

init : List String -> ( Model, Cmd Msg )
init flags =
    ( { args = flags }, Cmd.none )

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        NoOp ->
            ( model, Cmd.none )

main : Program (List String) Model Msg
main =
    Platform.worker
        { init = init
        , update = update
        , subscriptions = \_ -> Sub.none
        }

printArgs : Model -> Task Never ()
printArgs model =
    let
        argsWithProg = "elm" :: model.args
        argsWithoutProg = model.args
        arg = Maybe.withDefault "" (List.head (List.drop 2 model.args))
    in
    Process.sleep 0
        |> Task.andThen (\_ -> 
            Task.sequence
                [ Process.sleep 0 |> Task.andThen (\_ -> Task.succeed (Debug.log "argsWithProg" argsWithProg))
                , Process.sleep 0 |> Task.andThen (\_ -> Task.succeed (Debug.log "argsWithoutProg" argsWithoutProg))
                , Process.sleep 0 |> Task.andThen (\_ -> Task.succeed (Debug.log "arg" arg))
                ]
        )
        |> Task.map (\_ -> ())

subscriptions : Model -> Sub Msg
subscriptions _ =
    Sub.none

In Elm, we don’t have direct access to command-line arguments as we do in other languages. Instead, we can pass flags to our Elm program when it’s initialized.

The init function receives these flags as a List String. We store these arguments in our Model.

We use Platform.worker to create a headless Elm program that can process these arguments.

The printArgs function simulates the printing of arguments. Since Elm is primarily designed for web applications, we use Debug.log to output the values to the console.

To run this Elm program with command-line arguments, you would typically compile it to JavaScript and then run it with Node.js, passing the arguments:

$ elm make Main.elm --output=main.js
$ node main.js a b c d

This would output:

argsWithProg: ["elm","a","b","c","d"]
argsWithoutProg: ["a","b","c","d"]
arg: "c"

Note that in this Elm version, we’ve simulated the concept of os.Args by adding “elm” as the first element of argsWithProg. The actual program name isn’t directly available in Elm when run this way.

Remember that this is a simplified example. In real-world Elm applications, you would typically use ports or flags to pass initial data to your Elm program, rather than trying to access command-line arguments directly.