I wrote an Elm code snippet that would draw a square and change the square color between red and black every time when mouse is clicked.
However the case structure in the changeColor function doesn't work as expected, while the changeColor implemented with if structure will work.
What should I do to figure out what's going wrong? Thank you.
import Color exposing (red, black, blue, Color)
import Signal exposing ((<~))
import Graphics.Element exposing (Element, show)
import Graphics.Collage exposing (collage, square, filled, Form)
import Mouse
import Window
main : Signal Element
main =
scene <~ (Signal.foldp changeColor black Mouse.clicks)
scene : Color -> Element
scene color =
collage 600 600 [ filled_square color ]
changeColor : () -> Color -> Color
changeColor _ color =
case color of
black -> red
red -> black
--changeColor _ color =
-- if | color == black -> red
-- | color == red -> black
filled_square : Color -> Form
filled_square color = square 100 |> filled color
Lowercase names in case patterns are always considered variables, never constants. So your case statement will match color against a pattern variable black
, which succeeds, and binds the name black
to the value of color
inside the case branch (-> red
).
In this case the multi-way if
that you have in comments is the appropriate way to distinguish the cases.
Case expressions are used to distinguish cases in union types. You could for example explicitly model your program states with a union type like so:
import Color exposing (red, black, blue, Color)
import Signal exposing ((<~))
import Graphics.Element exposing (Element, show)
import Graphics.Collage exposing (collage, square, filled, Form)
import Mouse
import Window
type Model = Red | Black
main : Signal Element
main =
scene <~ (Signal.foldp changeColor Black Mouse.clicks)
scene : Model -> Element
scene model =
collage 600 600 [ filled_square (toColor model) ]
toColor : Model -> Color
toColor model =
case model of
Black -> black
Red -> red
changeColor : () -> Model -> Model
changeColor _ model =
case model of
Black -> Red
Red -> Black
filled_square : Color -> Form
filled_square color = square 100 |> filled color
The reason for doing this could be that you now have a finite, enumerable states for your program in an easy to find place. If you use just the colours, you only know this for sure by looking through the entire program. The case expression is exhaustive, it handles all states your program can be in. Whereas with a multi-way if on colours, who knows if those are the only colours possible to have in your program, especially once it grows larger than toy-example-size. If you don't match all the possible colours, you could run into a runtime crash of your application. (This is one of the few possible ways that could happen in Elm)