如何从Haskell中的自定义数据类型列表的每个元素中获取字段?

时间:2014-03-27 17:30:32

标签: haskell list-comprehension knapsack-problem

首先,如果标题令人困惑,我道歉 - 我不知道该怎么说。

我正在学习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]

感谢。

2 个答案:

答案 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解压缩对象列表后,可以将其传递给其他纯函数。