-- | Hash rate abstractions

module Data.Hashrate where

import Data.Money (ScalableAdditive(..))
import Data.Typeable

-- | Bitcoin mining algo
data SHA256 = SHA256 deriving (Show, Eq)
-- | Litecoin mining algo
data Scrypt = Scrypt deriving (Show, Eq)
-- | Ethereum mining algo
data ETHASH = ETHASH deriving (Show, Eq)
-- | Dash mining algo
data X11 = X11 deriving (Show, Eq)
-- | Zcash mining algo
data EQUIHASH = EQUIHASH deriving (Show, Eq)

class (Show a, Eq a, Typeable a) => MiningAlgorithm a

instance MiningAlgorithm SHA256
instance MiningAlgorithm Scrypt
instance MiningAlgorithm ETHASH
instance MiningAlgorithm X11
instance MiningAlgorithm EQUIHASH


-- | Mining hashrate, polymorphic
data Hashrate a = Hashrate
  { algorithm :: a
  -- ^ The algorithm
  , rate :: Double
  -- ^ Mining hashrate in h/sec
  } deriving (Show)


-- | Hashrate constructor
makeHashrate :: (MiningAlgorithm a) => a -> Double -> Hashrate a
makeHashrate = Hashrate

instance ScalableAdditive (Hashrate a) where
  (Hashrate a hr1) ^+^ (Hashrate _ hr2) = Hashrate a (hr1 + hr2)
  (Hashrate a hr1) ^-^ (Hashrate _ hr2) = Hashrate a (hr1 - hr2)
  (Hashrate a hr) ^* c = Hashrate a $ hr * c


kilo = 10.0 ^ 3
mega = 10.0 ^ 6
giga = 10.0 ^ 9
tera = 10.0 ^ 12