Search code examples
typeselm

Using numbers as types in Elm


I'm learning elm and I'm trying to use types to better describe my domain. But I got stuck here: I can't use number literals as types/type aliases? Is there an "elmish way" to do this?

module Main exposing (main)

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)


type alias Model =
    { pos : Int }

type Up = 1
type Down = -1
type Direction = Up | Down

type Msg
    = Go Direction


initialModel : Model
initialModel =
    { pos = 0 }


update : Msg -> Model -> Model
update msg model =
    case msg of
        Go Up ->
            { model | pos = model.pos + Up }

        Go Down ->
            { model | pos = model.pos + Down }


view : Model -> Html Msg
view model =
    div []
        [ button [ onClick Go Up ] [ text "+1" ]
        , div [] [ text <| String.fromInt model.count ]
        , button [ onClick Go Down ] [ text "-1" ]
        ]


main : Program () Model Msg
main =
    Browser.sandbox
        { init = initialModel
        , view = view
        , update = update
        }

(ellie link: https://ellie-app.com/7HRDRKHRCFDa1 )


Solution

  • In order to use Up and Down with operator +, they would have to be values, not types – values of the same type as the other operand. So define them as constants of type Int instead:

    up : Int
    up = 1
    
    down : Int
    down = -1
    

    Then you can write your update function as:

    update : Msg -> Model -> Model
    update msg model =
        case msg of
            Go Up ->
                { model | pos = model.pos + up }
    
            Go Down ->
                { model | pos = model.pos + down }
    

    For the full working code, see this Ellie. The only other change I made was to your buttons' onClick – it needs to be onClick <| Go Up to tell the compiler that Up is an argument to Go, and the result is an argument to onClick.