开发者

Implementing a very simple 'Wine Rating System' in Haskell

开发者 https://www.devze.com 2022-12-29 09:31 出处:网络
I have just started learning Haskell and have got stumped on how to add a rating to a custom data type.

I have just started learning Haskell and have got stumped on how to add a rating to a custom data type.

The data type I'm using has a name, a year and a tuple (userName and their rating), it looks like:

data Wine = Wine String Int [Rating] deriving (Eq,开发者_开发技巧Ord,Show,Read)
type Rating = (String, Int)

I wanted to allow a user to rate a given wine from a database, stored as [Wine] but cant figure out how to to it. Any pointers or suggestions would be greatly appreciated! Thanks.


Why not use record syntax?

data Wine = Wine { 
  wineName :: String,
  wineYear :: Int,
  wineRatings :: [Rating]
}

rateWine :: Wine -> Rating -> Wine
rateWine wine rating = wine { wineRatings = rating : wineRatings wine }


I hope this solves your problem:

addRating :: Wine -> Rating -> Wine
addRating (n, y, rs) r = (n, y, r:rs)


In addition to the problem of adding a rating to a single wine (solved nicely by the other posters), there's also two more tasks that need to be done:

  1. Locating the wine that needs to be rated. You're not 100% clear about how wines are identified, but I guess that'll be by name and year. So you need to make a function like findWineIndex :: String -> Int -> [Wine] -> Maybe Int - I'm using Maybe Int as the result to allow for the possibility that you're looking for a Chateau Briand 2025, or something like that.
  2. Replacing the 'old' wine by the updated in the database. That would be a function like replaceWineInList :: Int -> Wine -> [Wine] -> [Wine] which takes an index, an updated wine and the original database, and which returns the updated wine database.

However, managing the index explicitly is not the nicest way you can do this! (Not to mention that is inefficient as you'll be traversing the list twice, slightly messy with the Maybe handling and, dare I say it, the imperative way :)

You could also try defining a function updateFirstThat :: (a -> Bool) -> (a -> a) -> [a] -> [a] taking a predicate and an update function which applies the update to the first element that satisfies the predicate. An example use would be updateFirstThat (>3) (*2) [1..6] which should evaluate to [1,2,3,8,5,6].

I hope you can puzzle together a solution with these bits and pieces, otherwise just ask for a few more hints!

0

精彩评论

暂无评论...
验证码 换一张
取 消