【问题标题】:Accessing my own type (data type) inside my own type (data type2) in Haskell?在 Haskell 中我自己的类型(数据类型 2)中访问我自己的类型(数据类型)?
【发布时间】:2020-08-15 18:11:24
【问题描述】:

好的,所以我有两种类型:

data Ingredient = Ingredient { potato :: String, amount :: Int, cookingTime :: Int }

data Soup = Soup { availableTime :: Int, recipe :: [Ingredient], shoppingList :: [Ingredient], canBeDone :: Bool  }

现在,如果我想比较一种成分的“可用时间”和“烹饪时间”(基本上,如果我只有“可用时间”来煮整个汤,我就有足够的时间来烹饪该成分)。 如果我可以在汤中烹制配料,配料就会转移到购物清单列表中。 我该怎么做? 这是我想出的:

doIHaveTime :: Soup -> Soup
doIHaveTime Soup{availableTime = a, recipe = [Ingredient{cookingTime = b}] } = if a >= b then Soup{ shoppingList = b:xs } else show "Can't be done."

这种思维方式有意义吗? 这些是我得到的错误:

soupExample.hs:6:128: 错误: • 无法将类型“[Char]”与“Soup”匹配 预期类型:汤 实际类型:字符串 • 在表达式中:显示“无法完成”。 在表达式中: 如果 a >= b 那么 汤 {shoppingList = b : xs} 别的 显示“无法完成”。 在“doIHaveTime”的等式中: doIHaveTime (汤{availableTime = a,recipe = [Ingredient {cookingTime = b}]}) = 如果 a >= b 那么 汤 {shoppingList = b : xs} 别的 显示“无法完成”。 失败,已加载模块:无。

【问题讨论】:

  • recipe = [Ingredient{cookingTime = b}] 将只处理具有 一种 成分的配方,并在其他情况下崩溃。你可以使用recipe = is来绑定整个列表,或者做两种情况,recipe = []recipe = Ingredient{cookingTime = b} : is
  • 另外,Soup -> Soup 类型看起来是错误的,因为如果没有足够的时间,您不会返回汤。也许你想要Soup -> Maybe Soup
  • shoppingList 可能不应该是Soup 的一部分;那应该是Ingredients 的列表,独立于Soup 需要的任何成分。
  • 我应该提一下,记录字段访问是 Haskell 的弱点之一。一旦获得更多经验,您可能会想了解一些部分解决方案(尤其是 optics)。

标签: haskell


【解决方案1】:

要处理汤中的多种成分,您可以使用all :: (a -> Bool) -> [a] -> Bool 检查食谱中的每种成分是否可以在可用时间内煮熟:

​​>
enoughTime = all ((>=available) . cookingTime) ingredients

然后你必须在ifelse 分支中返回一个Soup。总的来说,这可能如下所示:

doIHaveTime :: Soup -> Soup
doIHaveTime soup@Soup{ availableTime = available, recipe = ingredients }
    = if enoughTime
        -- add ingredients to shoppingList and set canBeDone to True
        then soup { shoppingList = ingredients
                  , canBeDone = True }
        -- clear shoppingList and set canBeDone to False
        else soup { shoppingList = []
                  , canBeDone = False }
  where enoughTime = all ((>=available) . cookingTime) ingredients

请注意,我使用soup@Soup{ ... } 进行模式匹配并将值同时存储在变量soup 中。这样你只需要修改shoppingListcanBeDone这两个字段。

【讨论】:

  • 感谢您的帮助,但我仍然遇到一个错误。所以据我了解,在最后一行“where enoughTime = all ((>=available) .cookingTime) 成分”中都采用了一个函数,在这种情况下 >=,它测试当前成分的烹饪时间是否不在列表中成分的数量大于或等于顶部指定的可用时间。 (正确的?)。因此,“all”从 Soup 数据类型(可用)中获取一个参数,从成分数据类型(cookingTime)中获取一个参数,并沿着列表(成分)运行它们。是吗?
  • 我的实际程序适用于进程调度,我只在最后一行出现错误。这些是数据类型:` data Prozess = Prozess { pid :: String, Arrival :: Int, Computing :: Int} 派生(显示)数据 State = State { new :: [Prozess], run :: Prozess, ready :: [Prozess], 时间 :: Int, 图表 :: String }`
  • 这是函数:update_ready :: State -> State update_ready state@State { time = t, new = process } = if isReady --add to ready state list then state {ready = process } --else clear list else state { ready = []} where isReady = all ((>=time) .arrival) 进程
  • 只需将>=time 更改为>=ttime 是成员函数,t 是您在模式匹配时分配的局部变量。
猜你喜欢
  • 1970-01-01
  • 2018-09-17
  • 2013-10-15
  • 2020-05-19
  • 1970-01-01
  • 2010-12-03
  • 2014-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多