首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >函数式编程练习

函数式编程练习
EN

Stack Overflow用户
提问于 2015-09-13 19:29:53
回答 3查看 137关注 0票数 0

作为一个函数式编程练习,我想我应该编写一个小程序,按照盈利能力对mmo中的制作食谱进行排序。

在OO语言中,我会为每个菜谱创建策略对象,成员为Cost()、ExpectedRevenue()和Volume()。然后,我会把所有的对象放在一个列表中,并根据盈利能力/时间函数对它们进行排序。

试图在F#中实现同样的结果,但我不确定如何实现。我有一些互不相关的成本职能,例如:

代码语言:javascript
复制
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

然后,收入和数量的定义如下:

代码语言:javascript
复制
let rPM = 1.05
let vPM = 50

但我不知道现在该怎么办。列出看起来类似的元组

代码语言:javascript
复制
(name: string, cost:double, revenue:double, volume:int) 

然后对名单进行排序?感觉好像我错过了什么

有没有人能更好地使用功能概念呢?这类计算问题似乎很适合于功能风格。

非常感谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-09-13 21:22:37

这是一个相当复杂的问题,有多种可能的答案。而且,很难猜到关于你的域名的任何事情(我不知道你在玩什么游戏:-),所以我会尝试根据这个例子编造一些东西。

基本的功能方法是使用受歧视的结合来模拟不同的食谱。

代码语言:javascript
复制
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

另外,我们需要知道游戏中物品的价格:

代码语言:javascript
复制
type Prices = { Gold : float; Steel : float; FrogLegs : float }

现在您可以编写函数来计算菜谱的成本和预期收入:

代码语言:javascript
复制
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的记录,它需要一个您想要评估的配方。

这个例子应该给你一些想法--从一个受歧视的联盟开始,建立问题域的模型(不同的配方),然后在其中编写一个模式匹配的函数,这通常是一个很好的开始--但是很难用问题中的有限信息来多说。

票数 3
EN

Stack Overflow用户

发布于 2015-09-13 21:24:45

在函数式语言中,你只能用函数式做任何事。在这里,您可以定义共同的盈利功能,并使用它和List.sortBy对您的食谱进行排序。

代码语言:javascript
复制
// 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
票数 1
EN

Stack Overflow用户

发布于 2015-09-14 07:57:52

接受的答案是有点缺乏类型的安全性,我认为-你已经说过,FancySword是由黄金和钢铁,所以你不应该记得正确地配对黄金数量与黄金价格!类型系统应该为您检查,并防止意外的g * prices.Steel错误。

如果可能的资源类型的集合是固定的,那么这是度量单位的一个很好的用例。

代码语言:javascript
复制
[<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>类型的值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32553701

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档