作为一个函数式编程练习,我想我应该编写一个小程序,按照盈利能力对mmo中的制作食谱进行排序。
在OO语言中,我会为每个菜谱创建策略对象,成员为Cost()、ExpectedRevenue()和Volume()。然后,我会把所有的对象放在一个列表中,并根据盈利能力/时间函数对它们进行排序。
试图在F#中实现同样的结果,但我不确定如何实现。我有一些互不相关的成本职能,例如:
let cPM (ss,marble) = (15.0 * ss + 10.0 * marble + 0.031) / 5.0
let cTRef (tear,clay) = (tear + 10.0 * clay + 0.031) / 5.0然后,收入和数量的定义如下:
let rPM = 1.05
let vPM = 50但我不知道现在该怎么办。列出看起来类似的元组
(name: string, cost:double, revenue:double, volume:int) 然后对名单进行排序?感觉好像我错过了什么
有没有人能更好地使用功能概念呢?这类计算问题似乎很适合于功能风格。
非常感谢。
发布于 2015-09-13 21:22:37
这是一个相当复杂的问题,有多种可能的答案。而且,很难猜到关于你的域名的任何事情(我不知道你在玩什么游戏:-),所以我会尝试根据这个例子编造一些东西。
基本的功能方法是使用受歧视的结合来模拟不同的食谱。
type Recipe =
| FancySword of gold:float * steel:float // Sword can be created from gold & steel
| MagicalStone of frogLegs:float // Magical stone requires some number of frog legs另外,我们需要知道游戏中物品的价格:
type Prices = { Gold : float; Steel : float; FrogLegs : float }现在您可以编写函数来计算菜谱的成本和预期收入:
let cost prices recipe =
match recipe with
| FancySword(g, s) ->
// To create a sword, we need 2 pieces of gold and 15 pieces of steel
2.0 * g * prices.Gold + s * 15.0 * prices.Steel
| MagicalStone(l) -> l * prices.FrogLeg这需要所有prices的记录,它需要一个您想要评估的配方。
这个例子应该给你一些想法--从一个受歧视的联盟开始,建立问题域的模型(不同的配方),然后在其中编写一个模式匹配的函数,这通常是一个很好的开始--但是很难用问题中的有限信息来多说。
发布于 2015-09-13 21:24:45
在函数式语言中,你只能用函数式做任何事。在这里,您可以定义共同的盈利功能,并使用它和List.sortBy对您的食谱进行排序。
// recipe type with constants for Revenue, Volume and (ss,marble)
type recipe = {r: float; v: float; smth: float * float}
// list of recipes
let recipes = [
{r = 1.08; v = 47.0; smth = (28.0, 97.0)};
{r = 1.05; v = 50.0; smth = (34.0, 56.0)} ]
// cost function
let cPM (ss,marble) = (15.0 * ss + 10.0 * marble + 0.031) / 5.0
// profitability function with custom coefficients
let profitability recipe = recipe.r * 2.0 + recipe.v * 3.0 + cPM recipe.smth
// sort recipes by profitability
let sortedRecipes =
List.sortBy profitability recipes
// note: it's reordered now
printfn "%A" sortedRecipes发布于 2015-09-14 07:57:52
接受的答案是有点缺乏类型的安全性,我认为-你已经说过,FancySword是由黄金和钢铁,所以你不应该记得正确地配对黄金数量与黄金价格!类型系统应该为您检查,并防止意外的g * prices.Steel错误。
如果可能的资源类型的集合是固定的,那么这是度量单位的一个很好的用例。
[<Measure>] type Gold
[<Measure>] type Steel
[<Measure>] type FrogLegs
[<Measure>] type GameMoney
type Recipe = {
goldQty : float<Gold>
steelQty : float<Steel>
frogLegsQty : int<FrogLegs>
}
type Prices = {
goldPrice : float<GameMoney/Gold>
steelPrice : float<GameMoney/Steel>
frogLegsPrice : float<GameMoney/FrogLegs>
}
let recipeCost prices recipe =
prices.goldPrice * recipe.goldQty +
prices.steelPrice * recipe.steelQty +
// frog legs must be converted to float while preserving UoM
prices.frogLegsPrice * (recipe.frogLegsQty |> float |> LanguagePrimitives.FloatWithMeasure)
let currentPrices = {goldPrice = 100.0<GameMoney/Gold>; steelPrice = 50.0<GameMoney/Steel>; frogLegsPrice = 2.5<GameMoney/FrogLegs> }
let currentCost = recipeCost currentPrices
let fancySwordRecipe = {goldQty = 25.4<Gold>; steelQty = 76.4<Steel>; frogLegsQty = 0<FrogLegs>}
let fancySwordCost = currentCost fancySwordRecipe编译器现在将确保所有计算都签出。例如,在recipeCost函数中,它确保总计是一个float<GameMoney>。
由于您提到了卷,我认为您可以看到如何复制相同的模式来编写类型安全的函数,这些函数将将总配方卷计算为int<InventoryVolume>类型的值。
https://stackoverflow.com/questions/32553701
复制相似问题