Skip to content

Instantly share code, notes, and snippets.

@meditans
Created March 31, 2016 12:39
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 meditans/0d44a897c5cacb0923458bf4a1d7a15b to your computer and use it in GitHub Desktop.
Save meditans/0d44a897c5cacb0923458bf4a1d7a15b to your computer and use it in GitHub Desktop.
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Control.Lens
import Control.Monad.State.Lazy (State (..), get, runState)
---------------------------------------------------- Data Types
type Message = String
data Product = Product { _name :: String
, _price :: Int
} deriving (Show, Eq)
data VendingMachine = VendingMachine
{ _products :: [Product]
, _moneyInside :: Int
, _messageOnDisplay :: Message
} deriving (Show)
makeLenses ''Product
makeLenses ''VendingMachine
coffee = Product "coffee" 3
initVM = VendingMachine [] 0 "init"
---------------------------------------------------- VM Commands
vmInsertMoney :: Int -> State VendingMachine ()
vmInsertMoney amount = moneyInside += amount
vmAddProduct :: Product -> State VendingMachine ()
vmAddProduct newProduct = do
products %= (newProduct:)
messageOnDisplay .= "Thanks"
vmSelectProduct :: Product -> State VendingMachine (Either Message Product)
vmSelectProduct p = do
(VendingMachine ps money _) <- get
if p `elem` ps && money `isEnoughFor` p
then do moneyInside -= (p^.price)
return (Right p)
else do return (Left "Not enough money")
isEnoughFor :: Int -> Product -> Bool
amount `isEnoughFor` product = amount >= product^.price
----------------------------------------------------------- Demo
vmDemo :: State VendingMachine (Either Message Product)
vmDemo = do vmAddProduct coffee
vmInsertMoney 5
vmInsertMoney 10
vmSelectProduct coffee
main :: IO ()
main = print $ runState vmDemo initVM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment