有没有办法用相同的where子句为两个不同的函数构造一个结构?
我的代码:
bonusColBullet :: Bonus -> Bullet -> World -> World
bonusColBullet bn@(Bonus{bnpos=pos}) b w@(World{bullets=bs, bonuses=bns, score=s})
| doBoxesCollide bnlp bnrp blp brp = w{bullets=delete b bs, bonuses=delete bn bns, score=incVal s}
| otherwise = w
where
blp = bpos' - bSizeH --bullet corners
brp = bpos' + bSizeH
bnlp = pos - bnSizeH --bonus obj corners
bnrp = pos + bnSizeH
bpos' = bpos b
incVal s@(Score{sval=sv, multiplier}) = s{sval=sv+multiplier}
enemyColBullet :: Enemy -> Bullet -> World -> World
enemyColBullet e@(Enemy{epos=pos}) b w@(World{bullets=bs, enemies=es, score=s})
| doBoxesCollide elp erp blp brp = w{bullets=delete b bs, enemies=delete e es, score=incVal s}
| otherwise = w
where
blp = bpos' - bSizeH -- bullet corners
brp = bpos' + bSizeH
elp = pos - eSizeH -- enemy corners
erp = pos + eSizeH
bpos' = bpos b
incVal s@(Score{sval=sv, multiplier}) = s{sval=sv+multiplier}因为这样对我来说效率很低,所以我想应该有一种方法,只需要写where子句1,并以某种方式将其包含在这两个函数中?
如果有人能帮我解决这个问题,我会非常感激的!
向你问好,天夫。
发布于 2014-10-31 15:32:34
是啊!你说得对,这是可以考虑的。Haskell的一个很酷的特性可能会帮助你,那就是含糊不清。Haskell有两种歧义,在这种情况下您可以使用其中一种。第一种歧义被称为参数类型,例如,列表类型[x]存在于所有x,而不管x是什么,因此实际上有许多不同的函数-- reverse :: [x] -> [x],每个类型都可以放在这些列表中。唯一的问题是,有时您需要对这些参数进行约束,这样您就可以使用它们完成任务(reverse受到完全模糊的限制;它不能对元素做任何事情,但只能重新排序,并可能删除或重复它们)。约束歧义是一个称为类型类的特性。下面是我如何用它们来适应你的情况:
type Size = ____ -- fill this in with whatever that type actually is.
class Sprite s where
kill :: s -> World -> World
position :: s -> Size
size :: s -> Size
instance Sprite Bullet where
kill b w = w{bullets = delete b (bullets w)}
position = bpos
size = const bSizeH -- constant for all bullets, right?
instance Sprite Bonus where
kill bn w = w{bonuses = delete bn (bonuses w)}
position = bnpos
size = const bnSizeH
instance Sprite Enemy where
kill e w = w{enemies = delete e (enemies w)}
position = epos
size = const eSizeH现在,您可以编写一些更通用的内容:
collides :: (Sprite x, Sprite y) => x -> y -> Bool
collides x y = doBoxesCollide (px - sx) (px + sx) (py - sy) (py + sy)
where px = position x
py = position y
sx = size x
sy = size y
addScore :: World -> World
addScore w = w{score = s{sval = sval s + multiplier s}} where s = score w
killCollision :: (Sprite x, Sprite y) => x -> y -> World -> World
killCollision x y = if collides x y then addScore . kill x . kill y else id我们已经从你的22条线上升到了27条线,但是我们现在有很多更小的部分以更清晰的方式相互作用,并且不再重复我们自己。这是一个艺术的选择--这是否值得--这通常有助于一个程序的长期维护,但是如果你只是想把一个程序弄出来,复制粘贴就更快了。
那么,现在您可以编写bonusColBullet bn b w了,您只需编写killCollision bn b w,它就可以做同样的事情,对于敌人e,killCollision e b w也是如此。但你有更多的力量。假设你想让敌人吃他们与之冲突的奖金:但你没有得到分数。那就是if collides e bn then kill bn else id。或者,您可能会决定不同的精灵有不同的points,它们是值得的;然后将它们添加到Sprite类points :: x -> Points中(其中点是任意类型的值--想必是Integer,但我不想假设)。您可以将addScore修改为:
addScore :: (Sprite x, Sprite y) => x -> y -> World -> World
addScore x y w = w{score = s{sval = newscore}
where s = score w
newscore = sval s + multiplier s * (points x + points y)通过用killCollision替换addScore来修改addScore x y。就这样。现在,不同的敌人或奖金可以值不同的金额。只要多做一点工作,你就可以让一个吃了奖励的敌人从这个奖励中得到积分(这样,如果你杀了他们,你还能得到加分)。像那样的东西。
发布于 2014-10-31 14:24:36
有没有办法用相同的where子句为两个不同的函数构造一个结构?
where为您提供了一个与本地范围的绑定。因此,要在两个函数之间共享这一点,它们必须“在”where范围内。
更容易将where子句抛出。计算一次,并将x和y传递给您的函数。
main = do
let x = func a - c
y = func' b - c
someFunc x y
someOtherFunc x yhttps://stackoverflow.com/questions/26676752
复制相似问题