haskell - 如何在 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
这里发生了什么?是否可以将列表用作状态元组中的一个元素?
解决方案
在您的 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 }
这种最终样式的一个好处是不可能意外创建一个包含错误数量元素的“列表”。
推荐阅读
- jquery - 选择2:如何创建列表中已存在的选项
- java - 设置 XMLGregorianCalendar 的时区
- c++ - 如何使用 boost::process::system 运行脚本?
- postgresql - 如何在我的 postgres 图像中更正 set work_mem amd max_wal_size
- sql - 将表的选定列转换为 SQL Server 中的行,并将列标题保留为值
- angular - 预期的间谍
被调用一次。被调用 0 次 - javascript - 如何在 React 中对对象数组进行有条件的 reduce 调用?
- c# - C# ComboBox 显示名称并使用 id 作为值?
- azure-iot-hub - 突然的连接问题
- android - Room 的 `onDelete = CASCADE` 在迁移期间不起作用