假设我们在Haskell中有以下内容,
type Bag a = a -> Int
data Gems = Sapphire|Emerald|Diamond|Ruby deriving (Show)
myBag :: Bag Gems
myBag Sapphire = 3
myBag Diamond = 2
myBag Emerald = 0
emptyBag :: Bag Gems
emptyBag Sapphire = 0
emptyBag Diamond = 0
emptyBag Emerald = 0
我们如何定义一个函数addItem,以便addItem x b将一个项x出现添加到bag b?
答案 0 :(得分:2)
您需要类型
的功能addItem :: Gems -> Bag Gems -> Bag Gems
注意BagGems
的定义,这与
addItem :: Gems -> (Gems -> Int) -> Gems -> Int
因此,我们期望addItem
的定义开始
addItem gemToAdd bag gem = --some Int expression
好的,所以让我们考虑一下逻辑
gem
与gemToaAdd
不同,我们应该知道bag
给我们的内容从而
addItem gemToAdd bag gem = if gem == gemToAdd then (bag gem) + 1 else bag gem
你也可以写
addItem gemToAdd bag gem | gem == gemToAdd = (bag gem) + 1
| otherwise = bag gem
现在,由于Eq
未定义Gems
,因此会产生错误。解决这个问题的最简单方法是定义
data Gems = Sapphire|Emerald|Diamond|Ruby deriving (Show, Eq)
你完成了
答案 1 :(得分:0)
首先,你不能在Haskell中改变任何东西,一切都是不可改变的。所以你现在想做的事情是错误的。
myBag Sapphire = 3
永远是3。
所以你必须退回一个新包而不是更换它。
另外,我认为创建一个Gems列表而不是模式匹配会更好。就这样:
data Gems = Sapphire|Emerald|Diamond|Ruby deriving (Show, Eq)
type Gem = (Gems, Int)
type Bag = [Gem]
您现在可以执行
等操作[(Ruby, 30), (Sapphire, 20)] :: Bag
例如。
接下来我们希望能够调整这个包。
removeGem :: Gems -> Bag -> Bag
removeGem _ [] = []
removeGem gem (x:xs) | gem == (fst x) = removeGem gem xs
| otherwise = x : removeGem gem xs
此代码可让您从包中删除宝石。它非常简单,它只是通过列表并检查每个项目是否是选定的宝石。如果不是这样,它会将其添加到功能列表中。最后,它将返回一个没有选定gem的新列表。
使用此功能,我们可以使用以下代码将宝石添加到包中:
addToBag :: Gem -> Bag -> Bag
addToBag item@(gem,amount) bag =
case lookup gem bag of
Nothing -> item : bag
_ -> let (Just oldAmount) = lookup gem bag
in (gem, (amount + oldAmount)) : (removeGem gem bag)
此代码可让您将新宝石添加到包中,如下所示:
(Diamond, 10) `addToBag` [(Ruby, 30), (Sapphire, 20)] :: Bag
将返回:
[(Diamond,10),(Ruby,20),(Sapphire,30)]
“lookup”是一个在元组列表中查找“键”的函数。关键是第一个元组值,在我们的例子中是Gems。
如果查找找不到我们要添加的gem,它只会将其附加到列表中。
如果确实找到了它,我们会将其拥有的宝石数量存储到“oldAmount”中,删除宝石并将新金额和旧金额一起添加,以便为您的包创建一个新的宝石。例如:
(Ruby,20) `addToBag` [(Diamond,10),(Ruby,20),(Sapphire,30)]
将返回:
[(Ruby,40),(Diamond,10),(Sapphire,30)]
而不是:
[(Ruby,20),(Diamond,10),(Ruby,20),(Sapphire,30)]
因此,它会累计金额,而不是一遍又一遍地添加相同的宝石名称。
如果你想从包中找到宝石和金额,你可以简单地使用“查找”功能。
我希望这能回答你的问题。