为什么 case 表达式在此 Elm 代码中不起作用?

Why doesn't the case expression work in this Elm code?

我写了一个 Elm 代码片段,它会在每次单击鼠标时绘制一个正方形并在红色和黑色之间更改正方形颜色。

然而 case 结构在 changeColor 函数中没有按预期工作,而 changeColor 实现如果 结构将起作用。

我应该怎么做才能找出问题所在?谢谢。

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

模式变量(简答)

大小写模式中的小写名称始终被视为变量,而非常量。因此,您的 case 语句会将颜色与模式变量 black 匹配,这会成功,并将名称 black 绑定到 case 分支 (-> red) 内的 color 的值。

在这种情况下,您在评论中的多路 if 是区分案例的适当方式。

使用大小写表达式

格表达式用于区分union types中的格。例如,您可以使用联合类型显式地对程序状态建模,如下所示:

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

这样做的原因可能是您现在在一个容易找到的地方为您的程序提供了一个有限的、可枚举的状态。如果你只使用颜色,你只能通过查看整个程序才能确定这一点。 case 表达式是详尽无遗的,它处理您的程序可能处于的所有状态。而使用多路 if on colors,谁知道这些是否是您程序中唯一可能具有的颜色,尤其是当它变得比 toy-example 大时-尺寸。如果您没有匹配所有可能的颜色,您可能 运行 导致应用程序 运行 时间崩溃。 (这是 Elm 中可能发生的几种可能方式之一)