Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module serves as the main entry point for the library. It provides the types and operations for typical usage and is usually the only import required. The core concept is:
- Wrapping a numeric value representing bytes in a new type.
- Attaching phantom labels representing the units (e.g. K, M, ...).
This prevents mistakes, such as adding two different byte sizes or converting between sizes incorrectly.
Since: 0.1
Synopsis
- newtype Bytes (s :: Size) n = MkBytes n
- data Size
- data SomeSize n
- class Sized a where
- class RawNumeric a where
- class Conversion a where
- convert :: forall (t :: Size) -> SingSize t => forall a. Conversion a => a -> Converted t a
- class Normalize a where
- module Numeric.Algebra
- module Numeric.Literal.Integer
- module Numeric.Literal.Rational
- module Data.Bytes.Formatting
- class Parser a
- parse :: Parser a => Text -> Either Text a
- _MkBytes :: forall (s :: Size) n. Iso' (Bytes s n) n
- _MkSomeSize :: forall (s :: Size) n. (FromInteger n, MGroup n, SingSize s) => Iso' (SomeSize n) (Bytes s n)
- _B :: Prism' Size ()
- _K :: Prism' Size ()
- _M :: Prism' Size ()
- _G :: Prism' Size ()
- _T :: Prism' Size ()
- _P :: Prism' Size ()
- _E :: Prism' Size ()
- _Z :: Prism' Size ()
- _Y :: Prism' Size ()
- class Default a where
- def :: a
Introduction
The main idea is to attach phantom labels to the numeric bytes, so we can track the size units. This allows us to safely manipulate byte values without mixing up units, performing incorrect conversions, etc.
The core types are a newtype wrapper Bytes
and the Size
units:
newtype Bytes (s :: Size) n Source #
This is the core type for handling type-safe byte operations. It is
intended to be used as a simple wrapper over some numeric type,
equipped with a Size
tag.
To take full advantage of the API (e.g. normalize
), the underlying
numeric type should implement Semifield
or, ideally, Field
.
Examples
>>>
MkBytes @M 1000
MkBytes 1000
Since: 0.1
MkBytes n |
Instances
Byte units.
Since: 0.1
B | Bytes Since: 0.1 |
K | Kilobytes Since: 0.1 |
M | Megabytes Since: 0.1 |
G | Gigabytes Since: 0.1 |
T | Terabytes Since: 0.1 |
P | Petabytes Since: 0.1 |
E | Exabytes Since: 0.1 |
Z | Zettabytes Since: 0.1 |
Y | Yottabytes Since: 0.1 |
Instances
NFData Size Source # | Since: 0.1 | ||||
Defined in Data.Bytes.Size | |||||
Bounded Size Source # | Since: 0.1 | ||||
Enum Size Source # | Since: 0.1 | ||||
Generic Size Source # | |||||
Defined in Data.Bytes.Size
| |||||
Show Size Source # | Since: 0.1 | ||||
Eq Size Source # | Since: 0.1 | ||||
Ord Size Source # | Since: 0.1 | ||||
Hashable Size Source # | Since: 0.1 | ||||
Parser Size Source # | Since: 0.1 | ||||
TestEquality SSize Source # | Since: 0.1 | ||||
Defined in Data.Bytes.Size | |||||
type Rep Size Source # | Since: 0.1 | ||||
Defined in Data.Bytes.Size type Rep Size = D1 ('MetaData "Size" "Data.Bytes.Size" "si-bytes-0.1-inplace" 'False) (((C1 ('MetaCons "B" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "K" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "M" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "G" 'PrefixI 'False) (U1 :: Type -> Type))) :+: ((C1 ('MetaCons "T" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "P" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "E" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "Z" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Y" 'PrefixI 'False) (U1 :: Type -> Type))))) |
Basic Usage
Construction
There are several ways to construct a Bytes
type.
>>>
afromInteger 80 :: Bytes M Int
MkBytes 80Directly
>>>
MkBytes 80 :: Bytes M Int
MkBytes 80Optics (
optics-core
)>>>
import Optics.Core (review)
>>>
(review _MkBytes 70) :: Bytes G Int
MkBytes 70>>>
(review #unBytes 70) :: Bytes G Int
MkBytes 70
Unknown Size
We sometimes have to deal with unknown sizes at runtime, which presents
a problem. We handle this with the
type, which existentially
quantifies the SomeSize
Size
:
Wrapper for Bytes
, existentially quantifying the size. This is useful
when a function does not know a priori what size it should return e.g.
>>>
:{
getFileSize :: FilePath -> IO (SomeSize Float) getFileSize path = do -- getRawFileSize :: FilePath -> IO (Float, String) (bytes, units) <- getRawFileSize path pure $ case units of "B" -> hideSize $ MkBytes @B bytes "K" -> hideSize $ MkBytes @K bytes _ -> error "todo" :}
We define an equivalence relation on SomeSize
that takes units into
account. For instance,
>>>
hideSize (MkBytes @G 7) == hideSize (MkBytes @M 7_000)
True
Because we expose the underlying Bytes
in several ways (e.g. Show
,
the SSize
witness), this is technically unlawful for equality
as it breaks the extensionality law:
\[ x = y \implies f(x) = f(y). \]
Since: 0.1
Instances
Functor SomeSize Source # | Since: 0.1 |
Foldable SomeSize Source # | Since: 0.1 |
Defined in Data.Bytes.Internal fold :: Monoid m => SomeSize m -> m # foldMap :: Monoid m => (a -> m) -> SomeSize a -> m # foldMap' :: Monoid m => (a -> m) -> SomeSize a -> m # foldr :: (a -> b -> b) -> b -> SomeSize a -> b # foldr' :: (a -> b -> b) -> b -> SomeSize a -> b # foldl :: (b -> a -> b) -> b -> SomeSize a -> b # foldl' :: (b -> a -> b) -> b -> SomeSize a -> b # foldr1 :: (a -> a -> a) -> SomeSize a -> a # foldl1 :: (a -> a -> a) -> SomeSize a -> a # elem :: Eq a => a -> SomeSize a -> Bool # maximum :: Ord a => SomeSize a -> a # minimum :: Ord a => SomeSize a -> a # | |
Traversable SomeSize Source # | Since: 0.1 |
HasField "unSomeSize" (SomeSize n) n Source # | Since: 0.1 |
Defined in Data.Bytes.Internal | |
(k ~ A_Getter, a ~ n, b ~ n) => LabelOptic "unSomeSize" k (SomeSize n) (SomeSize n) a b Source # | Since: 0.1 |
Defined in Data.Bytes.Internal | |
(Field n, FromInteger n) => AGroup (SomeSize n) Source # | Since: 0.1 |
(FromInteger n, Semifield n) => AMonoid (SomeSize n) Source # | Since: 0.1 |
Defined in Data.Bytes.Internal | |
(ASemigroup n, FromInteger n, MGroup n) => ASemigroup (SomeSize n) Source # | Since: 0.1 |
Normed n => Normed (SomeSize n) Source # | Since: 0.1 |
FromInteger n => FromInteger (SomeSize n) Source # | Fixed size Since: 0.1 |
Defined in Data.Bytes.Internal afromInteger :: Integer -> SomeSize n Source # | |
FromRational n => FromRational (SomeSize n) Source # | Fixed size Since: 0.1 |
Defined in Data.Bytes.Internal afromRational :: Rational -> SomeSize n Source # | |
NFData n => NFData (SomeSize n) Source # | Since: 0.1 |
Defined in Data.Bytes.Internal | |
Show n => Show (SomeSize n) Source # | Since: 0.1 |
(Eq n, FromInteger n, MGroup n) => Eq (SomeSize n) Source # | Since: 0.1 |
(FromInteger n, MGroup n, Ord n) => Ord (SomeSize n) Source # | Since: 0.1 |
(FromInteger n, Hashable n, MGroup n) => Hashable (SomeSize n) Source # | Since: 0.1 |
(FromInteger n, MGroup n) => Conversion (SomeSize n) Source # | Since: 0.1 |
(FromInteger n, MGroup n, Normed n, Ord n) => Normalize (SomeSize n) Source # | Since: 0.1 |
Read n => Parser (SomeSize n) Source # | Since: 0.1 |
RawNumeric (SomeSize n) Source # | Since: 0.1 |
Sized (SomeSize n) Source # | Since: 0.1 |
MGroup n => MSemiSpace (SomeSize n) n Source # | Since: 0.1 |
MGroup n => MSpace (SomeSize n) n Source # | Since: 0.1 |
(Field n, FromInteger n) => Module (SomeSize n) n Source # | Since: 0.1 |
Defined in Data.Bytes.Internal | |
(FromInteger n, Semifield n) => Semimodule (SomeSize n) n Source # | Since: 0.1 |
Defined in Data.Bytes.Internal | |
(FromInteger n, Semifield n) => SemivectorSpace (SomeSize n) n Source # | Since: 0.1 |
Defined in Data.Bytes.Internal | |
(Field n, FromInteger n) => VectorSpace (SomeSize n) n Source # | Since: 0.1 |
Defined in Data.Bytes.Internal | |
type Converted t (SomeSize n) Source # | |
Defined in Data.Bytes.Internal | |
type Norm (SomeSize n) Source # | |
Defined in Data.Bytes.Internal | |
type Raw (SomeSize n) Source # | |
Defined in Data.Bytes.Internal | |
type HideSize (SomeSize n) Source # | |
Defined in Data.Bytes.Internal |
Sized
Fortunately, we do not have to directly use the constructor or singletons.
We can instead use the Sized
class.
Types that have a size.
Since: 0.1
Retrieves the size.
Examples
>>>
import Data.Bytes (Bytes (..))
>>>
sizeOf (MkBytes @G 7)
G
>>>
sizeOf (hideSize $ MkBytes @M 7)
M
>>>
import Data.Bytes.Network (NetBytes (..), Direction (..))
>>>
sizeOf (hideSize $ MkNetBytesP @Up @M 7)
M
Since: 0.1
hideSize :: a -> HideSize a Source #
Hides the size.
Examples
>>>
import Data.Bytes (Bytes (..))
>>>
hideSize (MkBytes @G 7)
MkSomeSize SG (MkBytes 7)
Instances
Sized (SomeSize n) Source # | Since: 0.1 | ||||
Sized (SomeNet n) Source # | Since: 0.1 | ||||
SingSize s => Sized (Bytes s n) Source # | Since: 0.1 | ||||
SingSize s => Sized (SomeNetDir s n) Source # | Since: 0.1 | ||||
Defined in Data.Bytes.Network.Internal
sizeOf :: SomeNetDir s n -> Size Source # hideSize :: SomeNetDir s n -> HideSize (SomeNetDir s n) Source # | |||||
Sized (SomeNetSize d n) Source # | Since: 0.1 | ||||
Defined in Data.Bytes.Network.Internal
sizeOf :: SomeNetSize d n -> Size Source # hideSize :: SomeNetSize d n -> HideSize (SomeNetSize d n) Source # | |||||
SingSize s => Sized (NetBytes d s n) Source # | Since: 0.1 | ||||
Optics
Once again, we can use optics for this.
>>>
import Optics.Core (review)
>>>
review _MkSomeSize (MkBytes 70 :: Bytes G Int)
MkSomeSize SG (MkBytes 70)
Elimination
RawNumeric
We provide the RawNumeric
class for conveniently unwrapping a type
to the underlying numeric value.
class RawNumeric a where Source #
Abstracts "wrapper" types for generically retrieving a raw numeric value.
Since: 0.1
Retrieves the underlying value.
Examples
>>>
import Data.Bytes (Bytes (..), Size (..), Sized (..))
>>>
toRaw (MkBytes @G 7)
7
>>>
toRaw (hideSize $ MkBytes @M 400)
400
>>>
import Data.Bytes.Network (Direction (..), NetBytes (..))
>>>
toRaw (MkNetBytesP @Up @G 7)
7
>>>
toRaw (hideSize $ MkNetBytesP @Up @G 7)
7
Since: 0.1
Instances
RawNumeric (SomeSize n) Source # | Since: 0.1 | ||||
RawNumeric (SomeNet n) Source # | Since: 0.1 | ||||
RawNumeric (Bytes s n) Source # | Since: 0.1 | ||||
RawNumeric (SomeNetDir s n) Source # | Since: 0.1 | ||||
Defined in Data.Bytes.Network.Internal
toRaw :: SomeNetDir s n -> Raw (SomeNetDir s n) Source # | |||||
RawNumeric (SomeNetSize d n) Source # | Since: 0.1 | ||||
Defined in Data.Bytes.Network.Internal
toRaw :: SomeNetSize d n -> Raw (SomeNetSize d n) Source # | |||||
RawNumeric (NetBytes d s n) Source # | Since: 0.1 | ||||
HasField
We can use HasField
for this too.
>>>
-- {-# LANGUAGE OverloadedRecordDot #-}
>>>
let x = MkBytes 7 :: Bytes G Int
>>>
x.unBytes
7
>>>
let y = hideSize x :: SomeSize Int
>>>
y.unSomeSize
7
Optics
Optics are another option. The underscore-prefixed optics unwrap one level at a time, since we can freely compose them.
>>>
import Optics.Core (view, (%))
>>>
let x = MkBytes 7 :: Bytes G Int
>>>
view _MkBytes x
7
>>>
-- notice we have to convert the numeric value since the requested
>>>
-- return type ('M') differs from the original ('G')
>>>
let y = hideSize x :: SomeSize Int
>>>
(view _MkSomeSize y) :: Bytes M Int
MkBytes 7000
>>>
view (_MkSomeSize % (_MkBytes @M)) y
7000
The -XOverloadedLabel
instances unwrap all the way to the underlying numeric
value.
>>>
view #unBytes x
7
>>>
view #unSomeSize y
7
Transformations
Converting Units
class Conversion a where Source #
This class allows one to transform a bytes type to any Size
. For types
with existentially quantified Size
(e.g. SomeSize
,
SomeNetSize
), this will "undo" the existential quantification.
Since: 0.1
convert_ :: forall (t :: Size). SingSize t => a -> Converted t a Source #
convert_ @_ @t x
converts x
to size t
.
Examples
>>>
let bytes = MkBytes 50_000 :: Bytes 'M Int
>>>
let gBytes = convert_ @_ @G bytes
>>>
:type gBytes
gBytes :: Bytes G Int>>>
gBytes
MkBytes 50
>>>
let bytes = hideSize (MkBytes 0.2 :: Bytes 'T Float)
>>>
let mBytes = convert_ @_ @M bytes
>>>
:type mBytes
mBytes :: Bytes M Float>>>
mBytes
MkBytes 200000.0
Since: 0.1
Instances
(FromInteger n, MGroup n) => Conversion (SomeSize n) Source # | Since: 0.1 |
(FromInteger n, MGroup n) => Conversion (SomeNet n) Source # | Since: 0.1 |
(FromInteger n, MGroup n, SingSize s) => Conversion (Bytes s n) Source # | Since: 0.1 |
(FromInteger n, MGroup n, SingSize s) => Conversion (SomeNetDir s n) Source # | Since: 0.1 |
Defined in Data.Bytes.Network.Internal convert_ :: forall (t :: Size). SingSize t => SomeNetDir s n -> Converted t (SomeNetDir s n) Source # | |
(FromInteger n, MGroup n) => Conversion (SomeNetSize d n) Source # | Since: 0.1 |
Defined in Data.Bytes.Network.Internal convert_ :: forall (t :: Size). SingSize t => SomeNetSize d n -> Converted t (SomeNetSize d n) Source # | |
(FromInteger n, MGroup n, SingSize s) => Conversion (NetBytes d s n) Source # | Since: 0.1 |
convert :: forall (t :: Size) -> SingSize t => forall a. Conversion a => a -> Converted t a Source #
Alternative to convert_
with -XTypeApplications, using
-XRequiredTypeArguments.
Examples
>>>
let bytes = MkBytes 50_000 :: Bytes 'M Int
>>>
let gBytes = convert G bytes
>>>
:type gBytes
gBytes :: Bytes G Int>>>
gBytes
MkBytes 50
Since: 0.1
Normalization
class Normalize a where Source #
Used for normalizing bytes b
such that
\[ 1 \le \text{normalize}(b) < 1000 \iff 1\text{ B} \le b < 1000\text{ Y}. \]
In the strictest sense, \(\textrm{normalize} : \mathcal{C} \rightarrow \mathcal{C}\) is not a homomorphism, as the combination of two normalized values may itself not be normalized.
However, because the normalized units varies with the value, normalize
always returns a type that existentially quantifies the size
(e.g. SomeSize
). Eq
for these types is defined in
terms of an equivalence class that takes units into account e.g.
1 P = 1,000 T = 1,000,000 G ...
. Viewed this way, normalize
is actually
an isomorphism, as it is essentially a no-op, never leaving the
equivalence class.
This means we can happily mix normalization with different functions without worrying about the order. The only requirement we have is that such functions respect substitution:
\[ x = y \implies f(x) = f(y). \]
This is certainly true for all the usual mathematical operations we would
normally use, e.g., AGroup
addition,
Module
scalar multiplication. On
the other hand, any functions that inspect the underlying numeric value or
Bytes types could easily break this law. As such they should be treated
with suspicion, at least when used in conjunction with normalize
.
The other consideration we must keep in mind is that the final result of a
series of computations may not be normalized. If this is desired, then
normalize
should be the last operation performed. Using normalize
in
the middle would not cause any harm (other than, perhaps, impacting
efficiency), but it would not guarantee the final result is normalized.
Since: 0.1
normalize :: a -> Norm a Source #
Normalizes the value.
Examples
>>>
let bytes = MkBytes 5000 :: Bytes 'M Int
>>>
normalize bytes
MkSomeSize SG (MkBytes 5)
>>>
let bytes = hideSize (MkBytes 0.01 :: Bytes 'T Float)
>>>
normalize bytes
MkSomeSize SG (MkBytes 10.0)
Since: 0.1
Instances
(FromInteger n, MGroup n, Normed n, Ord n) => Normalize (SomeSize n) Source # | Since: 0.1 | ||||
(FromInteger n, MGroup n, Normed n, Ord n) => Normalize (SomeNet n) Source # | Since: 0.1 | ||||
(FromInteger n, MGroup n, Normed n, Ord n, SingSize s) => Normalize (Bytes s n) Source # | Since: 0.1 | ||||
(FromInteger n, MGroup n, Normed n, Ord n, SingSize s) => Normalize (SomeNetDir s n) Source # | Since: 0.1 | ||||
Defined in Data.Bytes.Network.Internal
normalize :: SomeNetDir s n -> Norm (SomeNetDir s n) Source # | |||||
(FromInteger n, MGroup n, Normed n, Ord n) => Normalize (SomeNetSize d n) Source # | Since: 0.1 | ||||
Defined in Data.Bytes.Network.Internal
normalize :: SomeNetSize d n -> Norm (SomeNetSize d n) Source # | |||||
(FromInteger n, MGroup n, Normed n, Ord n, SingSize s) => Normalize (NetBytes d s n) Source # | Since: 0.1 | ||||
Defined in Data.Bytes.Network.Internal
|
Algebra
The built-in Num
class is abandoned in favor of
algebra-simple's
algebraic hierarchy based on abstract algebra. This is motivated by a
desire to:
- Provide a consistent API.
- Avoid
Num
's infelicities (e.g. nonsense multiplication, dangerousfromInteger
).
Bytes
and SomeSize
are both AGroup
s.
A Ring
instance is not provided because
multiplication is nonsensical:
\[ x \;\textrm{mb} \times y \;\textrm{mb} = xy \;\textrm{mb}^2. \]
Fortunately, multiplying bytes by some kind of scalar is both useful and
has an easy interpretation: Bytes
forms a Module
over a Ring
(resp. VectorSpace
over a
Field
). This allows us to multiply a Bytes
or
SomeSize
by a scalar in a manner consistent with the above API.
Examples
Addition/Subtraction
>>>
import Numeric.Algebra (ASemigroup ((.+.)), AGroup ((.-.)))
>>>
let mb1 = MkBytes 20 :: Bytes 'M Int
>>>
let mb2 = MkBytes 50 :: Bytes 'M Int
>>>
mb1 .+. mb2
MkBytes 70>>>
mb1 .-. mb2
MkBytes (-30)
>>>
let kb = MkBytes 50 :: Bytes 'K Int
>>>
-- mb1 .+. kb -- This would be a type error
Multiplication
>>>
import Numeric.Algebra (MSemiSpace ((.*)))
>>>
mb1 .* 10
MkBytes 200
Division
>>>
import Numeric.Algebra (MSpace ((.%)))
>>>
mb1 .% 10
MkBytes 2
One may wonder how the AGroup
instance
for SomeSize
could possibly work. It is possible (indeed, expected) that
we could have two SomeSize
s that have different underlying Bytes
types.
To handle this, the SomeSize
instance will convert both Bytes
to a
Bytes
'B
before adding/subtracting.
>>>
let some1 = hideSize (MkBytes 1000 :: Bytes 'G Double)
>>>
let some2 = hideSize (MkBytes 500_000 :: Bytes 'M Double)
>>>
some1 .+. some2
MkSomeSize SB (MkBytes 1.5e12)>>>
some1 .-. some2
MkSomeSize SB (MkBytes 5.0e11)
module Numeric.Algebra
module Numeric.Literal.Integer
module Numeric.Literal.Rational
Text
Pretty Printing
We provide several formatters for pretty-printing different byte types.
>>>
import Data.Default (Default (def))
>>>
let bf = MkFloatingFormatter (Just 2)
>>>
let b = MkBytes @G @Float 20.248
>>>
formatSized bf def b
"20.25 gb"
module Data.Bytes.Formatting
Parsing
Represents a megaparsec parser. Used for parsing byte types from
Text
.
Since: 0.1
Instances
Parser Direction Source # | Since: 0.1 |
Parser Size Source # | Since: 0.1 |
Read n => Parser (SomeSize n) Source # | Since: 0.1 |
Read n => Parser (SomeNet n) Source # | Since: 0.1 |
Read n => Parser (Bytes s n) Source # | Since: 0.1 |
Read n => Parser (SomeNetDir s n) Source # | Since: 0.1 |
Defined in Data.Bytes.Network.Internal | |
Read n => Parser (SomeNetSize d n) Source # | Since: 0.1 |
Defined in Data.Bytes.Network.Internal | |
Read n => Parser (NetBytes d s n) Source # | Since: 0.1 |
parse :: Parser a => Text -> Either Text a Source #
Parses various byte types from Text
. Parsing is
lenient in general. We support:
- Case-insensitivity.
- Optional leading/internal/trailing whitespace.
- Flexible names.
Bytes Examples
>>>
import Data.Bytes (Bytes, Size (..), SomeSize)
>>>
parse @(Bytes M Int) "70"
Right (MkBytes 70)
>>>
parse @(SomeSize Float) "100.45 kilobytes"
Right (MkSomeSize SK (MkBytes 100.45))
>>>
parse @(SomeSize Word) "2300G"
Right (MkSomeSize SG (MkBytes 2300))
>>>
parse @(SomeSize Float) "5.5 tb"
Right (MkSomeSize ST (MkBytes 5.5))
Network Examples
>>>
import Data.Bytes.Network (Direction (..), NetBytes, SomeNet, SomeNetDir, SomeNetSize)
>>>
parse @(NetBytes Up M Int) "70"
Right (MkNetBytes (MkBytes 70))
>>>
parse @(SomeNetSize Down Float) "100.45 kilobytes"
Right (MkSomeNetSize SK (MkNetBytes (MkBytes 100.45)))
>>>
parse @(SomeNetSize Up Word) "2300G"
Right (MkSomeNetSize SG (MkNetBytes (MkBytes 2300)))
>>>
parse @(SomeNetDir T Word) "2300 up"
Right (MkSomeNetDir SUp (MkNetBytes (MkBytes 2300)))
>>>
parse @(SomeNetDir M Word) "2300D"
Right (MkSomeNetDir SDown (MkNetBytes (MkBytes 2300)))
>>>
parse @(SomeNet Float) "5.5 tb Up"
Right (MkSomeNet SUp ST (MkNetBytes (MkBytes 5.5)))
>>>
parse @(SomeNet Float) "5.5 megabytes DOWN"
Right (MkSomeNet SDown SM (MkNetBytes (MkBytes 5.5)))
Since: 0.1
Optics
Core
_MkSomeSize :: forall (s :: Size) n. (FromInteger n, MGroup n, SingSize s) => Iso' (SomeSize n) (Bytes s n) Source #
Iso'
between SomeSize
and underlying Bytes
. Performs any necessary
conversions when going from SomeSize n -> Bytes s n
.
Examples
>>>
import Optics.Core (review, view)
>>>
review _MkSomeSize (MkBytes @K @Int 70)
MkSomeSize SK (MkBytes 70)
>>>
(view _MkSomeSize (hideSize $ MkBytes @K @Int 70)) :: Bytes B Int
MkBytes 70000
Since: 0.1
Size
Reexports
class Default a where Source #
A class for types with a default value.
Nothing
The default value for this type.
Instances
Default All | |
Defined in Data.Default.Class | |
Default Any | |
Defined in Data.Default.Class | |
Default CClock | |
Defined in Data.Default.Class | |
Default CDouble | |
Defined in Data.Default.Class | |
Default CFloat | |
Defined in Data.Default.Class | |
Default CInt | |
Defined in Data.Default.Class | |
Default CIntMax | |
Defined in Data.Default.Class | |
Default CIntPtr | |
Defined in Data.Default.Class | |
Default CLLong | |
Defined in Data.Default.Class | |
Default CLong | |
Defined in Data.Default.Class | |
Default CPtrdiff | |
Defined in Data.Default.Class | |
Default CSUSeconds | |
Defined in Data.Default.Class def :: CSUSeconds Source # | |
Default CShort | |
Defined in Data.Default.Class | |
Default CSigAtomic | |
Defined in Data.Default.Class def :: CSigAtomic Source # | |
Default CSize | |
Defined in Data.Default.Class | |
Default CTime | |
Defined in Data.Default.Class | |
Default CUInt | |
Defined in Data.Default.Class | |
Default CUIntMax | |
Defined in Data.Default.Class | |
Default CUIntPtr | |
Defined in Data.Default.Class | |
Default CULLong | |
Defined in Data.Default.Class | |
Default CULong | |
Defined in Data.Default.Class | |
Default CUSeconds | |
Defined in Data.Default.Class | |
Default CUShort | |
Defined in Data.Default.Class | |
Default Int16 | |
Defined in Data.Default.Class | |
Default Int32 | |
Defined in Data.Default.Class | |
Default Int64 | |
Defined in Data.Default.Class | |
Default Int8 | |
Defined in Data.Default.Class | |
Default Word16 | |
Defined in Data.Default.Class | |
Default Word32 | |
Defined in Data.Default.Class | |
Default Word64 | |
Defined in Data.Default.Class | |
Default Word8 | |
Defined in Data.Default.Class | |
Default Ordering | |
Defined in Data.Default.Class | |
Default DirectedFormatter Source # | Since: 0.1 |
Defined in Data.Bytes.Formatting.Direction | |
Default DirectionFormat Source # | Since: 0.1 |
Defined in Data.Bytes.Formatting.Direction | |
Default SizeFormat Source # | Since: 0.1 |
Defined in Data.Bytes.Formatting.Size def :: SizeFormat Source # | |
Default SizedFormatter Source # | |
Defined in Data.Bytes.Formatting.Size def :: SizedFormatter Source # | |
Default Integer | |
Defined in Data.Default.Class | |
Default () | |
Defined in Data.Default.Class | |
Default Double | |
Defined in Data.Default.Class | |
Default Float | |
Defined in Data.Default.Class | |
Default Int | |
Defined in Data.Default.Class | |
Default Word | |
Defined in Data.Default.Class | |
(Default a, RealFloat a) => Default (Complex a) | |
Defined in Data.Default.Class | |
Default (First a) | |
Defined in Data.Default.Class | |
Default (Last a) | |
Defined in Data.Default.Class | |
Default a => Default (Dual a) | |
Defined in Data.Default.Class | |
Default (Endo a) | |
Defined in Data.Default.Class | |
Num a => Default (Product a) | |
Defined in Data.Default.Class | |
Num a => Default (Sum a) | |
Defined in Data.Default.Class | |
Integral a => Default (Ratio a) | |
Defined in Data.Default.Class | |
Default a => Default (IO a) | |
Defined in Data.Default.Class | |
Default (Maybe a) | |
Defined in Data.Default.Class | |
Default [a] | |
Defined in Data.Default.Class | |
(Default a, Default b) => Default (a, b) | |
Defined in Data.Default.Class | |
Default r => Default (e -> r) | |
Defined in Data.Default.Class | |
(Default a, Default b, Default c) => Default (a, b, c) | |
Defined in Data.Default.Class | |
(Default a, Default b, Default c, Default d) => Default (a, b, c, d) | |
Defined in Data.Default.Class | |
(Default a, Default b, Default c, Default d, Default e) => Default (a, b, c, d, e) | |
Defined in Data.Default.Class | |
(Default a, Default b, Default c, Default d, Default e, Default f) => Default (a, b, c, d, e, f) | |
Defined in Data.Default.Class | |
(Default a, Default b, Default c, Default d, Default e, Default f, Default g) => Default (a, b, c, d, e, f, g) | |
Defined in Data.Default.Class |