- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
问题
我正在尝试用PureScript编写游戏引擎。我是新手,但是自从我之前经历过真实世界的Haskell(尽管我也没有太多使用Haskell处理“真实”事物的经验)以来,学习一直很顺利。在我的书中,将我的运行时错误尽可能多地转换为编译时错误的任何事情都是成功的-但是,如果该语言被证明过度限制了我抽象问题的能力,那么它可以消除一些胜利。
好的,因此,我正在尝试在HTML5 Canvas / context2d上的PureScript中构建2d游戏引擎(显然purescript-canvas为此提供了一个不错的选择-我更喜欢Elm的Graphics.Canvas模块,因为它映射了很多更接近实际的基础JS API,尤其是让我可以访问Canvas的各个像素。
在我现有的(未完成但可用的)JS引擎中,核心功能是我保留一个“ sprite”列表(异类,但它们都共享一个公共类),然后遍历它们以调用.update(timeDelta)
和.draw(context2d)
方法。
所有的精灵都有一个共同的接口,但是必须在底层支持根本不同的数据。一个可能具有x / y坐标;另一个(可能表示环境效果)可能具有“完成百分比”或其他动画状态。
问题是,我只是无法提出一个等效的抽象(到异类/共享类列表)来完成我需要做的事情,而又不会滥用FFI将我的方式破解成非常不纯净的代码。
解决方案(及其问题)
异构列表(duh)
显然,可以等效于异构列表的最佳抽象方法就是异构列表。
哈斯克尔风格
事实证明,Haskell(即欺骗性的GHC,而不是正式的规范/报告)提供了exactly what I want-您可以在保留类型约束的同时装箱类型信息,对列表中的所有项目应用单个多态函数,而无需突破型安全。这将是理想的选择,但是可惜PureScript目前不允许我表达如下类型:
data ShowBox = forall s. Show s => SB s
[Exists f]
列表,也不能只是将类型提取/重新添加为通用
forall a. (Draw a) => a
,我必须知道我要恢复的实际类型。我可以包含某种“标记”,告诉我应该提取哪种“真实”类型,但是如果我要提取这些类型的恶作剧,那么我也可能会用普通的JS进行编码。我可能要做的事情(对于列表,不一定是包含的精灵)。
draw
函数以为最外面的
drawThisParticularSprite
函数添加
update
同上。在所有可能的解决方案中可能是最糟糕的。
type Sprite = { data: Data, draw: Data -> DrawEffect, update: Data -> Data }
Data
是一些类型不合常规的东西,例如某种
Exists f
,并且
type DrawEffect = forall e. Eff (canvas :: Canvas | e) Context2D
draw
和
update
方法都将特定于各个记录,并且都“知道”要从
Data
中提取的真实类型。
ShowBox
必须存储其(隐藏的)成员的实例信息,因此,它会从其
Show
中知道要使用的
show
正确实例。自己对
最佳答案
我在这里假设您的Draw
类看起来像
class Draw a where
draw :: a -> DrawEffect
update :: a -> a
purescript-exists
选项可以工作,并且绝对是类型安全的,尽管您声称要删除而不是隐藏信息。
data DrawOps a = DrawOps { "data" :: a
, draw :: a -> DrawEffect
, update :: a -> a
}
Exists DrawOps
,可以将其放入列表中,例如:
drawables :: List (Exists DrawOps)
drawables = fromArray [ mkExists (DrawOps { "data": 1
, draw: drawInt
, update: updateInt
}
, mkExists (DrawOps { "data": "foo"
, draw: drawString
, update: updateString
}
]
runExists
(安全)解开类型,请注意
runExists
的类型会强制您忽略包装数据的类型:
drawAll :: List (Exists DrawOps) -> DrawEffect
drawAll = traverse (runExists drawOne)
where drawOne (DrawOps ops) = ops.draw ops."data"
data Drawable = Drawable { drawn :: DrawEffect
, updated :: Unit -> Drawable
}
DrawOps
中的操作的展开:
unfoldDrawable :: forall a. DrawOps a -> Drawable
unfoldDrawable (DrawOps ops)
= Drawable { drawn: ops.draw ops."data"
, updated: \_ -> unfoldDrawable (DrawOps (ops { "data" = ops.update ops."data" }))
}
Drawable
内容填充列表:
drawables :: List Drawable
drawables = fromArray [ unfoldDrawable 1 drawInt updateInt
, unfoldDrawable "foo" drawString updateString
]
drawAll :: List Drawable -> DrawEffect
drawAll = traverse drawOne
where drawOne (Drawable d) = d.drawn
updateAndDrawAll :: List Drawable -> DrawEffect
updateAndDrawAll = traverse updateAndDrawOne
where updateAndDrawOne (Drawable d) = (d.updated unit).drawn
关于purescript - 适当的抽象代替异构(但共享类)列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36992410/
来自 F# 世界,我习惯使用 |>将数据通过管道传输到函数中: [1..10] |> List.filter (fun n -> n % 2 = 0) |> List.map (fun n -> n
是否可以对 Purescript 中的类型构造函数施加某些限制?例如: newtype Name = Name String -- where length of String is > 5 最
我刚刚开始学习 Purescript,所以我希望这不是一个愚蠢的问题。 假设我们有一个对象 a = {x:1,y:2} 我们想要将 x 更改为等于 2。据我所知,如果我们使用 ST monad,我们将
我想知道如何在 PureScript 代码中添加注释。 在 Python 中,等价的是: # Here is a comment 或JavaScript // Another comment Pure
当在缩进位置使用三引号时,我肯定也会在输出 js 字符串中缩进: 在嵌套的 let 中比较这两个 let input1 = "T1\nX55.555Y-44.444\nX52.324Y-40.386"
PureScript by Example,在 The Eff Monad -> Handlers and Actions 部分指出“[效果]处理程序通常从集合中减去效果”。但是,这些示例相当不透明,
纯脚本列表中是否有 foreach 方法? foreach 方法获取列表的每一项并返回一个单位。 它是打印列表中每个项目的好方法。 编辑:我正在尝试下面建议的 traverse 方法,但出现错误 im
我首先是关于 Purescript 的。 我要将新字段添加到 Object 并将其作为函数参数发送。 但我找不到一个好的解决方案。 例如。 oldFiled = { title : "title",
我正在使用 Purescript 做第一步并复制 "hello world" app . 测试通过。我故意破坏了测试。 module Test.Main where import Prelude im
我是 Purescript 的新手,所以这可能是一个幼稚的问题。 我想编写一个 Purescript 函数,它从浏览器上的 HTML 输入元素读取输入,并将一些输出写入另一个 HTML 输入元素。 使
我想制作一个非常人性化的开发环境,我正在考虑使用 PureScript 来提供语言部分。我看到开箱即用,Show不适用于作为 Show 实例的事物的记录: log (show {a:5}) “试试 P
有没有办法做类似的事情 first = {x:0} second = {x:1,y:1} both = [first, second] 使得 both推断为 {x::Int | r}或类似的东西? 我
我正在使用 purescript-halogen,当捕获到子组件的消息时,我想滚动到 div 的底部。 但是,在 Halogen 中似乎不存在滚动 Action 控制。 那么,我该如何 Scroll
大家。我想在 Purescript 的记录数组中找到一个元素,但由于我不熟悉 Purescripot,所以无法解决。 我有一个包含银行记录的数组banks。 这是银行记录的类型。 type Bank
大家。我想在 Purescript 的记录数组中找到一个元素,但由于我不熟悉 Purescripot,所以无法解决。 我有一个包含银行记录的数组banks。 这是银行记录的类型。 type Bank
我有一个类型为 Either String (Either String Int) 的对象.我想将其折叠为 Either String Int 类型的对象. PureScript 中是否有为此提供的函
我想使用 Purescript 的 Halogen 编写前端的特定组件。 例如,我想使用卤素创建一个注册表单。它看起来像下面这样: module RegistrationForm where impo
这对我来说似乎是一个奇怪的问题,但我已经通过了 purescript-datetime和 purescript-js-date而我就是找不到获取当前信息的方法 DateTime .是否有一些隐藏的库函
当目标平台是 JavaScript 时,我正在寻找一种控制 Purescript 代码翻译格式的方法。 “spago bundle-app”为 ES5 版本生成 JavaScript 代码。 spag
我正在使用 purescript-halogen 构建类似电子表格的表格(类似于 Handsontable )。如果您双击一个单元格,一个 html 输入元素将呈现为相应表格单元格的子元素(并且不会为
我是一名优秀的程序员,十分优秀!