如何在 CodeWorld 中构造活动 Of() 中的状态?

How to structure the state in activityOf() in CodeWorld?

我探索了CodeWorld框架中activityOf(state_0, change, picture)的用法。 状态被描述为一个元组。我测试了让元组中的一个元素成为列表的可能性,因为我认为这将非常有用并使编码更紧凑。

在下面的示例中,我展示了如果我只打印出 u_list 中的第一个元素 u1 似乎是可行的。我可以通过上下键控制值,时间 t 继续。 u_list 中的第二个元素 u2 就在那里,没有改变。

program = activityOf(state_0, change, picture)
state_0(rs) = (t0, u_list_0)

u_list_0 = [u10,u20]
t0 = 0
u10 = 0
u20 = 7

t_of((t_value,_)) = t_value
u1_of((_, ulist)) = ulist#1 
u2_of((_, ulist)) = ulist#2

change((t, u_list), KeyPress("Up"))    = (t_of((t,u_list)), [u1_of((t, u_list))+1])
change((t, u_list), KeyPress("Down"))  = (t_of((t,u_list)), [u1_of((t, u_list))-1])
change((t, u_list), TimePassing(dt))   = (t_of((t,u_list))+dt, u_list)
change((t, u_list), other)             = (t, u_list)
picture((t, u_list))                   = pictures [translated(lettering(printed(t_of((t, u_list)))),0,1),
                                                              lettering(printed(u1_of((t, u_list))))]

但是,如果我将最后一行的示例更改为仅打印出 u2,即将 u1_of (..) 更改为 u2_of(..) 那么我将不会出现编译错误和程序 运行s。但是,如果我向上和向下按下任何键,那么我会在定义了 u2_of() 的代码的第 11 行出现 运行time 错误。

错误信息:

List index is too large.
When evaluating:  error, called  in the standard library  idxErrorTooLarge, called     
in the standard library  #, used at  Line 11, Column 21 in your code

这是怎么回事? 是否可以将列表用作状态元组中的一个元素?

Link 到 运行 https://code.world/#PBKh1Aucqqxg48ePyxxAuUg

在向上和向下键处理程序中,您正在将列表更改为只有一个元素:

change((t, u_list), KeyPress("Up"))    = (t_of((t,u_list)), [u1_of((t, u_list))+1])
change((t, u_list), KeyPress("Down"))  = (t_of((t,u_list)), [u1_of((t, u_list))-1])
                                                            ^^^^^^^^^^^^^^^^^^^^^^

如果您在按下其中一个键后请求列表的第二个元素(如 picture 所做的那样),则不会有任何可访问的元素。你可能想要这样的东西:

[u1_of((t, u_list))-1, u2_of(t, u_list)]

作为文体评论:在 Haskell 中使用这样的访问器函数是相当不寻常的,如果模式匹配能让你到达你想去的地方。例如,这会更加地道:

change ((t, [r, c]), KeyPress "Up"  ) = (t, [r+1, c])
change ((t, [r, c]), KeyPress "Down") = (t, [r-1, c])

这会更加地道:

data GameState = GameState
    { t :: Int
    , r :: Int
    , c :: Int
    }

change (s, KeyPress "Up"  ) = s { r = r s + 1 }
change (s, KeyPress "Down") = s { r = r s - 1 }

这种最终样式的一个好处是,不可能不小心创建一个元素数量错误的“列表”。