Skip to content

Instantly share code, notes, and snippets.

@devshorts
Last active December 30, 2015 07:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devshorts/7794811 to your computer and use it in GitHub Desktop.
Save devshorts/7794811 to your computer and use it in GitHub Desktop.
shopping 2
module Foo where
import Control.Monad
import Common.Utils
import Data.List
import Data.Maybe
newtype Price = Price { getPrice :: Float } deriving (Show, Eq)
data Buyable = Meat | Fruit deriving (Show, Eq)
data Coupon =
All Float
| Next Int Float
| Nth Int Buyable Float deriving Eq
instance Show Coupon where
show (All x) = "All coupons " ++ show x
show (Next n x) = show n ++ "th at " ++ show x ++ "%"
show (Nth n b x) = "Take $" ++ show x ++ " dollars off the " ++
show n ++ "th " ++ show b
data Cart =
Discount Coupon
| Product Buyable Price
deriving (Show, Eq)
cartList :: [Cart]
cartList = [Product Fruit $ Price 2.0,
Discount $ All 0.5,
Discount $ Nth 1 Meat 0.5,
Product Meat $ Price 1.0,
Product Meat $ Price 2.0]
updateCart :: Float -> Cart -> Cart
updateCart percent (Product buyable price) = Product buyable newPrice
where
newPrice = Price $ (getPrice price) * percent
updateCart _ coupon = coupon
isProduct :: Cart -> Bool
isProduct (Product _ _) = True
isProduct (Discount _) = False
isBuyable :: Buyable -> Cart -> Bool
isBuyable target (Product b _) = target == b
isBuyable _ _ = False
nextIndex :: Int -> (a -> Bool) -> [a] -> Maybe Int
nextIndex start predicate list = index
where
mIndex = findIndex predicate . drop (start ) $ list
index = mIndex >>= \idx -> return (idx + start)
getNth :: Int -> Int -> (a -> Bool) -> [a] -> Maybe Int
getNth start count predicate list
| count == 0 = index
| count /= 0 = index >>= next >>= continue
where
index = nextIndex start predicate list
next idx = return (idx + 1)
continue idx = getNth idx (count - 1) predicate list
updateByPredicate :: [Cart] -> Int -> Int -> (Cart -> Bool) -> Float -> [Cart]
updateByPredicate list nth offset predicate percent =
case getNth offset nth predicate list of
Just idx -> let (oldList, curr:rest) = splitAt idx list
updated = updateCart percent curr
in oldList++[updated]++rest
Nothing -> list
procElem :: Cart -> [Cart] -> Int -> [Cart]
procElem (Discount(All percent)) list offset =
map (updateCart percent) list
procElem (Discount(Next nth percent)) list offset =
updateByPredicate list nth offset isProduct percent
procElem (Discount(Nth nth buyable percent)) list offset =
updateByPredicate list nth offset (isBuyable buyable) percent
procElem _ list offset = list
mapCart :: [Cart] -> [Cart]
mapCart list = mappedCart list
where
iterateElements (count, cart) element = (count + 1, procElem element cart count)
mappedCart = snd . foldl(iterateElements) (0, list)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment