首页 > 解决方案 > 如何在 CodeWorld 的 activityOf() 中构造状态?

问题描述

我探索了 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(..),则不会出现编译错误并且程序运行。但是,如果我向上和向下按任何键,则会在定义 u2_of() 的代码的第 11 行出现运行时错误。

错误信息:

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

这里发生了什么?是否可以将列表用作状态元组中的一个元素?

运行链接https://code.world/#PBKh1Aucqqxg48ePyxxAuUg

标签: haskellsimulationcodeworld

解决方案


在您的 up 和 down 键处理程序中,您将列表更改为只有一个元素:

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 }

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


推荐阅读