I'm looking to learn how to write efficient Haskell code. This snippet works, but the run time is slow. How can I write faster Haskell code?
Input: maxPrice = 7
Input: vendorsDelivery = [5, 4, 2, 3]
Input: vendorsProducts = [[1, 1, 1],[3, -1, 3],[-1, 2, 2],[5, -1, -1]]
Output: [1,2]
(fastest delivery time for a given order)
import Data.List
import Data.List.Split
import Control.Monad
data Vendor a = Vendor { vendorNbr :: Int
, deliveryTime :: Int
, itemPrice :: Int
} deriving (Show)
populate d v = map (filter (\x -> itemPrice x /= (-1))) $ transpose $ map (\(x,y,z) -> map (\xs -> Vendor x y xs) z) $ zip3 [0..] d v
minimalBasketPrice mP vD vP = nub . get1 $ foldr (\x xs -> if get2 x < (get2 xs) then x else xs) (possible !! 0) possible
where combos = sequence (populate vD vP)
possible = filter (\(_,_,x) -> x <= mP) [((accu vendorNbr y), (total deliveryTime y), (total itemPrice y)) | y <- combos]
-- | Helper Functions
get1 (x,_,_) = x
get2 (_,x,_) = x
total f = foldr (\x y -> (f x) + y) 0
accu f = foldr (\x y -> (f x) : y) []
filter (\(_,_,x) -> x <= mP) [((accu vendorNbr y), (total deliveryTime y), (total itemPrice y)) | y <- combos]
I want to filter the smallest total deliveryTime of a set of items but I'm not sure how to do that without possibly removing the only possible solution from the set. I mean there could be a possible case where the only set of items you can purchase is not the smallest deliveryTime but the most expensive and in that case you'd want to return that deliveryTime. \$\endgroup\$