{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE TypeFamilyDependencies #-} {-# LANGUAGE TypeOperators #-} #if ( __GLASGOW_HASKELL__ >= 806 ) {-# LANGUAGE NoStarIsType #-} #endif {- | Copyright: (c) 2018-2020 Kowainik SPDX-License-Identifier: MPL-2.0 Maintainer: Kowainik This module contains type aliases for memory data units. According to the official standard, there exist two naming conventions for memory units. Standard measure prefixes are multipliers of @10@. But there are alternative prefixes which end with @bi@ and they are represented as powers of @2@. The difference can be displayed in the following table: +------------+----------------+----------+ | Name | Multipliers | In bytes | +============+================+==========+ | 'Kilobyte' | \( 10 ^ 3 \) | 1000 | +------------+----------------+----------+ | 'Kibibyte' | \( 2 ^ {10} \) | 1024 | +------------+----------------+----------+ | 'Megabyte' | \( 10 ^ 6 \) | 1000000 | +------------+----------------+----------+ | 'Mebibyte' | \( 2 ^ {20} \) | 1048576 | +------------+----------------+----------+ -} module Membrain.Units ( -- * Simple Bit , Nibble , Byte -- * Decimal , Kilobyte , Megabyte , Gigabyte , Terabyte , Petabyte , Exabyte , Zettabyte , Yottabyte -- * Binary , Kibibyte , Mebibyte , Gibibyte , Tebibyte , Pebibyte , Exbibyte , Zebibyte , Yobibyte -- * Unit symbols , UnitSymbol , KnownUnitSymbol , unitSymbol ) where import GHC.Exts (Proxy#, proxy#) import GHC.TypeLits (KnownSymbol, Symbol, symbolVal') import GHC.TypeNats (type (*), Nat) type Bit = 1 type Nibble = 4 type Byte = 8 type Kilobyte = 1000 * Byte type Megabyte = 1000 * Kilobyte type Gigabyte = 1000 * Megabyte type Terabyte = 1000 * Gigabyte type Petabyte = 1000 * Terabyte type Exabyte = 1000 * Petabyte type Zettabyte = 1000 * Exabyte type Yottabyte = 1000 * Zettabyte type Kibibyte = 1024 * Byte type Mebibyte = 1024 * Kibibyte type Gibibyte = 1024 * Mebibyte type Tebibyte = 1024 * Gibibyte type Pebibyte = 1024 * Tebibyte type Exbibyte = 1024 * Pebibyte type Zebibyte = 1024 * Exbibyte type Yobibyte = 1024 * Zebibyte {- | Type-level function to map memory units multipliers to proper symbols. >>> :kind! UnitSymbol Bit UnitSymbol Bit :: Symbol = "b" >>> :kind! UnitSymbol Byte UnitSymbol Byte :: Symbol = "B" >>> :kind! UnitSymbol Kilobyte UnitSymbol Kilobyte :: Symbol = "kB" >>> :kind! UnitSymbol Mebibyte UnitSymbol Mebibyte :: Symbol = "MiB" -} type family UnitSymbol (unit :: Nat) = (res :: Symbol) | res -> unit type instance UnitSymbol 1 = "b" type instance UnitSymbol 4 = "n" type instance UnitSymbol 8 = "B" type instance UnitSymbol 8000 = "kB" type instance UnitSymbol 8000000 = "MB" type instance UnitSymbol 8000000000 = "GB" type instance UnitSymbol 8000000000000 = "TB" type instance UnitSymbol 8000000000000000 = "PB" type instance UnitSymbol 8000000000000000000 = "EB" type instance UnitSymbol 8000000000000000000000 = "ZB" type instance UnitSymbol 8000000000000000000000000 = "YB" type instance UnitSymbol 8192 = "KiB" type instance UnitSymbol 8388608 = "MiB" type instance UnitSymbol 8589934592 = "GiB" type instance UnitSymbol 8796093022208 = "TiB" type instance UnitSymbol 9007199254740992 = "PiB" type instance UnitSymbol 9223372036854775808 = "EiB" type instance UnitSymbol 9444732965739290427392 = "ZiB" type instance UnitSymbol 9671406556917033397649408 = "YiB" -- | Constraint alias for 'KnownSymbol' calculated by 'UnitSymbol'. type KnownUnitSymbol (mem :: Nat) = KnownSymbol (UnitSymbol mem) {- | Term-level function to get value of the 'UnitSymbol' type family. Can be used only with @-XTypeApplications@. >>> unitSymbol @Terabyte "TB" >>> unitSymbol @Yobibyte "YiB" -} unitSymbol :: forall (mem :: Nat) . KnownUnitSymbol mem => String unitSymbol = symbolVal' (proxy# :: Proxy# (UnitSymbol mem)) {-# INLINE unitSymbol #-}