Skip to content

Instantly share code, notes, and snippets.

@olligobber
Last active January 12, 2020 04:11
Show Gist options
  • Save olligobber/159ad9cb6362151efb3e6e9d3693ad91 to your computer and use it in GitHub Desktop.
Save olligobber/159ad9cb6362151efb3e6e9d3693ad91 to your computer and use it in GitHub Desktop.
Use of Haskell's type checker for calculations of rates
{-# LANGUAGE TypeOperators #-}
import Rates
data Second
data GP
data NatRune
data LawRune
data AddyArrowBought
data AddyArrowShot
data OgressKill
data OgressDamage
data LawDrop
data NatDrop
ogressHP :: OgressDamage // OgressKill
ogressHP = Rate 82
rapidFireRate :: AddyArrowShot // Second
rapidFireRate = Rate 1.8
ogressLawDrop :: OgressKill // LawDrop
ogressLawDrop = Rate 16.57
ogressNatDrop :: OgressKill // NatDrop
ogressNatDrop = Rate 16.57
ogressNatAmount :: NatRune // NatDrop
ogressNatAmount = Rate 11.5
ogressLawAmount :: LawRune // LawDrop
ogressLawAmount = Rate 11.5
telegrab :: NatRune // LawRune
telegrab = Rate 4
arrowCost :: GP // AddyArrowBought
arrowCost = Rate 80
-- 20% of arrows are lost when shot
shoot :: AddyArrowShot // AddyArrowBought
shoot = Rate 5
natPerKill :: NatRune // OgressKill
natPerKill = (telegrab &* ogressLawAmount &/ ogressLawDrop) <> (ogressNatAmount &/ ogressNatDrop)
gpPerKill :: (OgressDamage // Second) -> (GP // OgressKill)
gpPerKill dps = arrowCost &/ shoot &* rapidFireRate &/ dps &* ogressHP
gpPerNat :: (OgressDamage // Second) -> (GP // NatRune)
gpPerNat dps = gpPerKill dps &/ natPerKill
main :: IO ()
main = do
putStrLn "Enter DPS"
dps <- Rate . toRational <$> (readLn :: IO Double)
putStrLn "GP Per Nat Rune is"
print (fromRational $ getVal $ gpPerNat dps :: Double)
{-# LANGUAGE TypeOperators, ExplicitNamespaces #-}
module Rates (
Rate(..),
(&*),
rev,
(&/),
RatRate,
type (//)
) where
import Data.Semigroup (stimes)
newtype Rate a b x = Rate { getVal :: x }
instance Functor (Rate a b) where
fmap f = Rate . f . getVal
instance Applicative (Rate a b) where
pure = Rate
(<*>) = fmap . getVal
instance Monad (Rate a b) where
(>>=) = flip ($) . getVal
instance Num x => Semigroup (Rate a b x) where
(<>) = fmap . (+) . getVal
stimes = fmap . (*) . fromIntegral
instance Num x => Monoid (Rate a b x) where
mempty = Rate 0
infixl 7 &*
infixl 7 &/
(&*) :: Num x => Rate a b x -> Rate b c x -> Rate a c x
a &* b = Rate $ getVal a * getVal b
rev :: Fractional x => Rate a b x -> Rate b a x
rev = Rate . recip . getVal
(&/) :: Fractional x => Rate a b x -> Rate c b x -> Rate a c x
a &/ b = a &* rev b
type RatRate a b = Rate a b Rational
type a // b = RatRate a b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment