首先,如果标题令人困惑,我道歉 - 我不知道该怎么说。
我正在学习Haskell并处理Knapsack Problem,但是列表理解存在问题。
data Object = Item { name :: String,
weight:: Double,
profit :: Double,
efficiency :: Double }
deriving (Read, Show)
我有一个从.csv文件中获取列表并计算效率并对其进行排序的函数:
getItemsAsList
= do
body <- readFile "items.csv"
let ls = split '\n' body
let lc = map (split ',') ls
let itemList = map (loadItem) lc
let sorted = sortItems efficiency itemList
return sorted
使用的功能:
loadItem :: [[Char]] -> Object
loadItem (n:ow:op:xs) = Item n w p (p/w)
where
w = read ow :: Double
p = read op :: Double
sortItems :: Ord a => (t -> a) -> [t] -> [t]
sortItems fn [ ] = [ ]
sortItems fn (pivot:rest)
= sortItems fn [x | x <- rest, (fn x) > (fn pivot)]
++ [pivot] ++
sortItems fn [x | x <- rest, (fn x) <= (fn pivot)]
split :: Char -> [Char] -> [[Char]]
split _ [] = []
split delim str = if before == [] then
split delim (drop 1 remainder)
else
before: split delim (drop 1 remainder)
where
(before, remainder) = span (/=delim) str
我要做的是编写一个函数,该函数将遍历getItemsAsList
函数返回的列表,并从每个元素中获取weight
字段的值并将它们相加。一旦我理解了如何获取元素,我就可以实现对问题的贪婪解决方案。
此外,getItemsAsList
函数返回IO [Object]
感谢。
答案 0 :(得分:2)
要从单个Object
获得权重,请执行weight obj
。因此,要从Object
列表的每个元素中获取权重,请执行map weight objlist
或[weight obj | obj <- objlist]
。此外,Prelude
具有sum
功能,其功能与您期望的完全相同。把它们放在一起,你就完成了。
答案 1 :(得分:0)
您将getItemsAsList
(一个monadic函数)的结果视为正常值而不是IO操作。
monad的概念通常被解释为它是一个盒子,你可以解压缩&#34;来自(使用<-
运算符)的值。当您从纯函数中调用它时,您无法解压缩该值,而只是将其保留在框中。 (这是IO [Object]
的内容,它是一个包含Object列表值的IO框)。但是,您可以在monad中自由使用纯函数。
解决方法是从monad中调用并解包getItemsAsList
的值,然后将其传递给其他纯函数以执行其余任务。
使用<-
运算符从getItemsAsList解压缩对象列表后,可以将其传递给其他纯函数。