Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance Haskell:使用相同where子句的两个不同函数_Performance_Function_Haskell - Fatal编程技术网

Performance Haskell:使用相同where子句的两个不同函数

Performance Haskell:使用相同where子句的两个不同函数,performance,function,haskell,Performance,Function,Haskell,有没有一种方法可以使用相同的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,

有没有一种方法可以使用相同的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子句,并以某种方式使其对两个函数都可包含

如果有人能在这方面帮助我,我将不胜感激

致以最良好的祝愿, 斯凯夫

有没有一种方法可以使用相同的where子句为两个不同的函数创建一个结构

其中提供了具有本地范围的绑定。所以要在两个函数之间共享,它们必须在where范围内

更简单的方法是将where子句浮动出来。例如,计算一次,然后将x和y传递给函数

main = do
   let x = func a - c
       y = func' b - c

   someFunc x y
   someOtherFunc x y
有没有一种方法可以使用相同的where子句为两个不同的函数创建一个结构

其中提供了具有本地范围的绑定。所以要在两个函数之间共享,它们必须在where范围内

更简单的方法是将where子句浮动出来。例如,计算一次,然后将x和y传递给函数

main = do
   let x = func a - c
       y = func' b - c

   someFunc x y
   someOtherFunc x y

是的!你说得对,这是可以考虑的。Haskell中的一个很酷的特性可能会帮助你,那就是模糊性。Haskell有两种歧义,在本例中可以使用其中一种。第一种模糊性称为参数类型,例如,列表类型[x]对于所有x都存在,不管x是什么,因此实际上有很多不同的函数::[x]->[x],每个类型都有一个函数,可以放在这些列表中。唯一的问题是,有时你需要对这些参数进行约束,这样你就可以用它们来做事情,相反,这些参数受到总的模糊性的约束;它不能对元素做任何事情,但只能对它们重新排序,并可能删除或重复它们。约束歧义是一种称为类型类的特征。以下是我如何使用它们来适应您的情况:

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行,但我们现在有很多更小的部分以更清晰的方式相互作用,不再重复我们自己。无论这是否值得,这都是一个艺术性的选择——它通常有助于程序的长期维护,但如果你只是想让程序出现,复制粘贴通常会更快

所以现在你可以在写Bonuscolbolbullet bn b w的地方写killCollision bn b w,它做同样的事情,对于敌人e来说killCollision e b w也是如此。但是你有了更多的力量。假设你想让敌人吃掉他们碰撞的奖励:但你不会因此得到分数。那就是如果碰撞e bn然后杀死B bn else id。或者你可以决定不同的精灵有不同的价值点;然后将点添加到Sprite类points::x->points,其中points是点的任何Num类型-可能是整数,但我不想假设。将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)

您可以通过将addScore替换为addScore x y来修改killCollision。就这样。现在,不同的敌人或奖金可能值不同的金额。再多做一点工作,你就可以让一个吃了奖金的敌人从奖金中获得积分,这样,如果你杀死了他们,你仍然可以获得奖金积分。像那样的东西。

是的!你说得对,这是可以考虑的。Haskell中的一个很酷的特性可能会帮助你,那就是模糊性。Haskell有两种歧义,在本例中可以使用其中一种。第一种模糊性称为参数类型,例如,列表类型[x]对于所有x都存在,不管x是什么,因此实际上有很多不同的函数::[x]->[x],每个类型都有一个函数,可以放在这些列表中。唯一的问题是,有时你需要对这些参数进行约束,这样你就可以用它们来做事情,相反,这些参数受到总的模糊性的约束;它不能对元素做任何事情,但只能对它们重新排序,并可能删除或重复它们。约束歧义是一种称为类型类的特征。以下是我如何使用它们来适应您的情况:

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行,但我们现在有很多更小的部分以更清晰的方式相互作用,不再重复我们自己。无论这是否值得,这都是一个艺术性的选择——它通常有助于程序的长期维护,但如果你只是想让程序出现,复制粘贴通常会更快

所以现在你可以在写Bonuscolbolbullet bn b w的地方写killCollision bn b w,它做同样的事情,对于敌人e来说killCollision e b w也是如此。但是你有了更多的力量。假设你想让敌人吃掉他们碰撞的奖励:但你不会因此得到分数。那就是如果碰撞e bn然后杀死B bn else id。或者你可以决定不同的精灵有不同的价值点;然后你登了广告 d到Sprite类points::x->points,其中points是任意Num类型的点-可能是整数,但我不想假设。将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)

您可以通过将addScore替换为addScore x y来修改killCollision。就这样。现在,不同的敌人或奖金可能值不同的金额。再多做一点工作,你就可以让一个吃了奖金的敌人从奖金中获得积分,这样,如果你杀死了他们,你仍然可以获得奖金积分。类似的东西。

请向我们展示您的实际代码,以便我们可以帮助您。@AaditMShah我已经用实际代码编辑了我的问题,希望这能有所帮助。看起来您可以计算出冲突的代码,因为这是它们之间的共同点。试着把这些大函数分解成小函数。当where子句中有3个以上的表达式时,开始考虑重构可能是一个好主意。BPO、bSizeH和其他表达式来自哪里?这些是常数吗?如果是这样,那么创建一个bulletCollides函数,该函数取一个位置并返回一个Bool。@bheklillr这也是我的想法,但我不知道怎么做,因为两个函数都使用两个对象的位置计算相同的值,但是使用不同的对象,需要使用不同的函数来获取它们的位置。请向我们展示您的实际代码,以便我们可以帮助您。@AaditMShah我已经用实际代码编辑了我的问题,希望这会有所帮助。看起来很像您可以算出计算碰撞的代码,因为这是他们之间的共同点。试着把这些大函数分解成小函数。当where子句中有3个以上的表达式时,开始考虑重构可能是一个好主意。BPO、bSizeH和其他表达式来自哪里?这些是常数吗?如果是这样,那么创建一个bulletCollides函数,该函数取一个位置并返回一个Bool。@bheklillr这也是我的想法,但我不知道怎么做,因为两个函数都使用两个对象的位置计算相同的值,但是使用不同的对象,需要不同的函数来获取它们的位置。谢谢你的回复,不幸的是,这不是我的案例的一个选项。我意识到一个示例代码与我的实际代码不够接近,所以我用实际代码更新了我的问题。谢谢你的回复,不幸的是,这不是我的案例的选项。我意识到一个示例代码与我的实际代码不够接近,所以我用实际代码更新了我的问题。很好的解决方案,描述得很好,非常感谢!我以前考虑过使用类型/类,但我不知道如何在这种情况下应用它,感谢您花时间编写关于如何使用它的详细解释和代码,我相信这将对我有很大帮助!很好的解决方案,描述得很好,非常感谢!我以前考虑过使用类型/类,但我不知道如何在这种情况下应用它,感谢您花时间编写关于如何使用它的详细解释和代码,我相信这将对我有很大帮助!