- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设您正在 Haskell 中构建一个相当大的模拟。有许多不同类型的实体,它们的属性会随着模拟的进行而更新。例如,假设您的实体称为猴子、大象、熊等。
维护这些实体状态的首选方法是什么?
我想到的第一个也是最明显的方法是:
mainLoop :: [Monkey] -> [Elephant] -> [Bear] -> String
mainLoop monkeys elephants bears =
let monkeys' = updateMonkeys monkeys
elephants' = updateElephants elephants
bears' = updateBears bears
in
if shouldExit monkeys elephants bears then "Done" else
mainLoop monkeys' elephants' bears'
mainLoop
中明确提到的每种类型的实体已经很难看。函数签名。你可以想象如果你有 20 种实体,它会变得多么糟糕。 (20 对于复杂的模拟来说并非不合理。)所以我认为这是一种 Not Acceptable 方法。但它的优点是函数像
updateMonkeys
他们的工作非常明确:他们获取猴子列表并返回一个新的。
mainLoop
的签名:
mainLoop :: GameState -> String
mainLoop gs0 =
let gs1 = updateMonkeys gs0
gs2 = updateElephants gs1
gs3 = updateBears gs2
in
if shouldExit gs0 then "Done" else
mainLoop gs3
GameState
进入状态单子(monad)并调用
updateMonkeys
等在
do
.没关系。有些人宁愿建议我们用函数组合来清理它。也很好,我想。 (顺便说一句,我是 Haskell 的新手,所以也许我对其中的一些错误。)
updateMonkeys
这样的函数不要从他们的类型签名中给你有用的信息。你不能确定他们在做什么。当然,
updateMonkeys
是一个描述性的名字,但这是一个小小的安慰。当我传入
god object并说“请更新我的全局状态”,我觉得我们回到了命令世界。感觉就像是另一个名字的全局变量:你有一个对全局状态做某事的函数,你调用它,你希望它是最好的。 (我想你仍然避免了一些在命令式程序中会出现在全局变量中的并发问题。但是,并发几乎不是全局变量唯一的错误。)
stomp :: Elephant -> Monkey -> (Elephant, Monkey)
stomp elephant monkey =
(elongateEvilGrin elephant, decrementHealth monkey)
updateElephants
中被调用,因为这是我们检查是否有任何大象在任何猴子的踩踏范围内的地方。在这种情况下,你如何优雅地将变化传播给猴子和大象?在我们的第二个示例中,
updateElephants
接受并返回一个上帝对象,因此它可以影响这两种变化。但这只会进一步混淆水域并强化我的观点:使用上帝对象,您实际上只是在改变全局变量。如果您不使用上帝对象,我不确定您将如何传播这些类型的更改。
Monkey
,
Elephant
等对象。我可能有类方法可以在所有活体动物的集合中进行查找。也许您可以按位置、ID 等进行查找。由于查找函数底层的数据结构,它们将保持在堆上分配。 (我假设 GC 或引用计数。)它们的成员变量会一直发生变异。任何类的任何方法都可以使任何其他类的任何活体动物发生变异。例如。一个
Elephant
可能有
stomp
会降低传入的健康状况的方法
Monkey
对象,并且没有必要通过它
最佳答案
答案是functional reactive programming (玻璃钢)。它混合了两种编码风格:组件状态管理和时间相关值。由于FRP实际上是一整套设计模式,所以我想更具体一点:我推荐Netwire .
基本思想非常简单:您编写许多小的、自包含的组件,每个组件都有自己的本地状态。这实际上等同于时间相关值,因为每次查询此类组件时,您可能会得到不同的答案并导致本地状态更新。然后你结合这些组件来形成你的实际程序。
虽然这听起来很复杂且效率低下,但实际上它只是围绕常规函数的一个非常薄的层。 Netwire 实现的设计模式受到 AFRP(箭头函数响应式编程)的启发。它可能足够不同,值得拥有自己的名字(WFRP?)。您可能想阅读 tutorial .
无论如何,下面是一个小演示。你的构建 block 是电线:
myWire :: WireP A B
particle :: WireP [Particle] Particle
time :: WireP a Time
pure 15 :: Wire a Integer
-- or even:
15 :: Wire a Integer
integral_ 3 . 15
10 + 2*time
integral_ (0, 0) . integral_ (0, 0) . pure (2, 1)
stats . keyDown Spacebar <|> "stats currently disabled"
关于haskell - 在 Haskell 中维护复杂状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15467925/
在 Haskell 中,类型声明使用双冒号,即 (::),如 not::Bool -> Bool。 但是在许多语法与 Haskell 类似的语言中,例如榆树、 Agda 、他们使用单个冒号(:)来声明
insertST :: StateDecoder -> SomeState -> Update SomeState SomeThing insertST stDecoder st = ... Stat
如果这个问题有点含糊,请提前道歉。这是一些周末白日梦的结果。 借助 Haskell 出色的类型系统,将数学(尤其是代数)结构表达为类型类是非常令人愉快的。我的意思是,看看 numeric-prelud
我有需要每 5 分钟执行一次的小程序。 目前,我有执行该任务的 shell 脚本,但我想通过 CLI 中的键为用户提供无需其他脚本即可运行它的能力。 实现这一目标的最佳方法是什么? 最佳答案 我想你会
RWH 面世已经有一段时间了(将近 3 年)。在在线跟踪这本书的渐进式写作之后,我渴望获得我的副本(我认为这是写书的最佳方式之一。)在所有相当学术性的论文中,作为一个 haskell 学生,读起来多么
一个经典的编程练习是用 Lisp/Scheme 编写一个 Lisp/Scheme 解释器。可以利用完整语言的力量来为该语言的子集生成解释器。 Haskell 有类似的练习吗?我想使用 Haskell
以下摘自' Learn You a Haskell ' 表示 f 在函数中用作“值的类型”。 这是什么意思?即“值的类型”是什么意思? Int 是“值的类型”,对吗?但是 Maybe 不是“值的类型”
现在我正在尝试创建一个基本函数,用于删除句子中的所有空格或逗号。 stringToIntList :: [Char] -> [Char] stringToIntList inpt = [ a | a
我是 Haskell 的新手,对模式匹配有疑问。这是代码的高度简化版本: data Value = MyBool Bool | MyInt Integer codeDuplicate1 :: Valu
如何解释这个表达式? :t (+) (+3) (*100) 自 和 具有相同的优先级并且是左结合的。我认为这与 ((+) (+3)) (*100) 相同.但是,我不知道它的作用。在 Learn
这怎么行 > (* 30) 4 120 但这不是 > * 30 40 error: parse error on input ‘*’ 最佳答案 (* 30) 是一个 section,它仍然将 * 视为
我想创建一个函数,删除满足第二个参数中给定谓词的第一个元素。像这样: removeFirst "abab" ( 'b') = "abab" removeFirst [1,2,3,4] even =
Context : def fib(n): if n aand returns a memoized version of the same function. The trick is t
我明白惰性求值是什么,它是如何工作的以及它有什么优势,但是你能解释一下 Haskell 中什么是严格求值吗?我似乎找不到太多关于它的信息,因为惰性评估是最著名的。 他们各自的优势是什么。什么时候真正使
digits :: Int -> [Int] digits n = reverse (x) where x | n digits 1234 = [3,1,2,4]
我在 F# 中有以下代码(来自一本书) open System.Collections.Generic type Table = abstract Item : 'T -> 'U with ge
我对 Haskell 比较陌生,过去几周一直在尝试学习它,但一直停留在过滤器和谓词上,我希望能得到帮助以帮助理解。 我遇到了一个问题,我有一个元组列表。每个元组包含一个 (songName, song
我是 haskell 的初学者,我试图为埃拉托色尼筛法定义一个简单的函数,但它说错误: • Couldn't match expected type ‘Bool -> Bool’
我是 Haskell 语言的新手,我在使用 read 函数时遇到了一些问题。准确地说,我的理解是: read "8.2" + 3.8 应该返回 12.0,因为我们希望返回与第二个成员相同的类型。我真正
当我尝试使用真实项目来驱动它来学习 Haskell 时,我遇到了以下定义。我不明白每个参数前面的感叹号是什么意思,我的书上好像也没有提到。 data MidiMessage = MidiMessage
我是一名优秀的程序员,十分优秀!