2019-10-13 18:37:08 +02:00
|
|
|
|
{-# LANGUAGE PartialTypeSignatures #-}
|
|
|
|
|
{-# LANGUAGE StandaloneDeriving #-}
|
|
|
|
|
{-# LANGUAGE ViewPatterns #-}
|
|
|
|
|
{-# LANGUAGE RoleAnnotations #-}
|
|
|
|
|
{-# LANGUAGE RecordWildCards #-}
|
2019-08-31 19:17:27 +02:00
|
|
|
|
{-# LANGUAGE DeriveTraversable #-}
|
2019-10-13 18:37:08 +02:00
|
|
|
|
{-# LANGUAGE DeriveFoldable #-}
|
|
|
|
|
{-# LANGUAGE DeriveFunctor #-}
|
|
|
|
|
{-# LANGUAGE TemplateHaskell #-}
|
|
|
|
|
{-# LANGUAGE NoTypeSynonymInstances #-}
|
2019-08-31 19:17:27 +02:00
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
-- | Common data types for Xanthous
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
module Xanthous.Data
|
2019-09-29 16:54:52 +02:00
|
|
|
|
( -- *
|
2019-10-13 18:37:08 +02:00
|
|
|
|
Position'(..)
|
|
|
|
|
, Position
|
2019-08-31 19:17:27 +02:00
|
|
|
|
, x
|
|
|
|
|
, y
|
|
|
|
|
|
|
|
|
|
, Positioned(..)
|
2019-09-15 19:00:28 +02:00
|
|
|
|
, _Positioned
|
2019-08-31 19:17:27 +02:00
|
|
|
|
, position
|
|
|
|
|
, positioned
|
|
|
|
|
, loc
|
2019-09-15 19:00:28 +02:00
|
|
|
|
, _Position
|
2019-09-13 21:24:05 +02:00
|
|
|
|
, positionFromPair
|
2019-09-29 16:54:52 +02:00
|
|
|
|
, addPositions
|
|
|
|
|
, diffPositions
|
|
|
|
|
, stepTowards
|
|
|
|
|
, isUnit
|
2019-08-31 19:17:27 +02:00
|
|
|
|
|
2019-10-13 18:37:08 +02:00
|
|
|
|
-- *
|
|
|
|
|
, Per(..)
|
|
|
|
|
, invertRate
|
|
|
|
|
, invertedRate
|
|
|
|
|
, (|*|)
|
|
|
|
|
, Ticks(..)
|
|
|
|
|
, Tiles(..)
|
|
|
|
|
, TicksPerTile
|
|
|
|
|
, TilesPerTick
|
|
|
|
|
, timesTiles
|
|
|
|
|
|
2019-09-07 20:49:59 +02:00
|
|
|
|
-- *
|
|
|
|
|
, Dimensions'(..)
|
|
|
|
|
, Dimensions
|
|
|
|
|
, HasWidth(..)
|
|
|
|
|
, HasHeight(..)
|
|
|
|
|
|
2019-08-31 19:17:27 +02:00
|
|
|
|
-- *
|
|
|
|
|
, Direction(..)
|
|
|
|
|
, opposite
|
|
|
|
|
, move
|
|
|
|
|
, asPosition
|
2019-09-29 16:54:52 +02:00
|
|
|
|
, directionOf
|
2019-09-02 19:56:25 +02:00
|
|
|
|
|
|
|
|
|
-- *
|
2019-09-10 02:54:33 +02:00
|
|
|
|
, Neighbors(..)
|
|
|
|
|
, edges
|
|
|
|
|
, neighborDirections
|
|
|
|
|
, neighborPositions
|
2019-11-16 03:20:01 +01:00
|
|
|
|
|
|
|
|
|
-- *
|
|
|
|
|
, Hitpoints(..)
|
2019-08-31 19:17:27 +02:00
|
|
|
|
) where
|
|
|
|
|
--------------------------------------------------------------------------------
|
2019-09-02 19:56:25 +02:00
|
|
|
|
import Xanthous.Prelude hiding (Left, Down, Right)
|
|
|
|
|
import Test.QuickCheck (Arbitrary, CoArbitrary, Function)
|
|
|
|
|
import Test.QuickCheck.Arbitrary.Generic
|
|
|
|
|
import Data.Group
|
2019-09-10 02:54:33 +02:00
|
|
|
|
import Brick (Location(Location), Edges(..))
|
2019-10-13 18:37:08 +02:00
|
|
|
|
import Data.Monoid (Product(..), Sum(..))
|
|
|
|
|
import Data.Aeson.Generic.DerivingVia
|
|
|
|
|
import Data.Aeson (ToJSON, FromJSON)
|
2019-08-31 19:17:27 +02:00
|
|
|
|
--------------------------------------------------------------------------------
|
2019-09-02 19:56:25 +02:00
|
|
|
|
import Xanthous.Util (EqEqProp(..), EqProp)
|
|
|
|
|
import Xanthous.Orphans ()
|
2019-09-29 16:54:52 +02:00
|
|
|
|
import Xanthous.Util.Graphics
|
2019-08-31 19:17:27 +02:00
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
2019-10-13 18:37:08 +02:00
|
|
|
|
-- fromScalar ∘ scalar ≡ id
|
|
|
|
|
class Scalar a where
|
|
|
|
|
scalar :: a -> Double
|
|
|
|
|
fromScalar :: Double -> a
|
|
|
|
|
|
|
|
|
|
instance Scalar Double where
|
|
|
|
|
scalar = id
|
|
|
|
|
fromScalar = id
|
|
|
|
|
|
|
|
|
|
newtype ScalarIntegral a = ScalarIntegral a
|
|
|
|
|
deriving newtype (Eq, Ord, Num, Enum, Real, Integral)
|
|
|
|
|
instance Integral a => Scalar (ScalarIntegral a) where
|
|
|
|
|
scalar = fromIntegral
|
|
|
|
|
fromScalar = floor
|
|
|
|
|
|
|
|
|
|
deriving via (ScalarIntegral Integer) instance Scalar Integer
|
|
|
|
|
deriving via (ScalarIntegral Word) instance Scalar Word
|
2019-08-31 19:17:27 +02:00
|
|
|
|
|
2019-10-13 18:37:08 +02:00
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
data Position' a where
|
|
|
|
|
Position :: { _x :: a
|
|
|
|
|
, _y :: a
|
|
|
|
|
} -> (Position' a)
|
|
|
|
|
deriving stock (Show, Eq, Generic, Ord, Functor, Foldable, Traversable)
|
|
|
|
|
deriving anyclass (NFData, Hashable, CoArbitrary, Function)
|
|
|
|
|
deriving EqProp via EqEqProp (Position' a)
|
|
|
|
|
deriving (ToJSON, FromJSON)
|
|
|
|
|
via WithOptions '[ FieldLabelModifier '[Drop 1] ]
|
|
|
|
|
(Position' a)
|
|
|
|
|
makeLenses ''Position'
|
|
|
|
|
|
|
|
|
|
type Position = Position' Int
|
|
|
|
|
|
|
|
|
|
instance Arbitrary a => Arbitrary (Position' a) where
|
2019-08-31 19:17:27 +02:00
|
|
|
|
arbitrary = genericArbitrary
|
|
|
|
|
shrink = genericShrink
|
|
|
|
|
|
2019-10-13 18:37:08 +02:00
|
|
|
|
instance Num a => Semigroup (Position' a) where
|
2019-08-31 19:17:27 +02:00
|
|
|
|
(Position x₁ y₁) <> (Position x₂ y₂) = Position (x₁ + x₂) (y₁ + y₂)
|
|
|
|
|
|
2019-10-13 18:37:08 +02:00
|
|
|
|
instance Num a => Monoid (Position' a) where
|
2019-08-31 19:17:27 +02:00
|
|
|
|
mempty = Position 0 0
|
|
|
|
|
|
2019-10-13 18:37:08 +02:00
|
|
|
|
instance Num a => Group (Position' a) where
|
|
|
|
|
invert (Position px py) = Position (negate px) (negate py)
|
|
|
|
|
|
|
|
|
|
-- | Positions convert to scalars by discarding their orientation and just
|
|
|
|
|
-- measuring the length from the origin
|
|
|
|
|
instance (Ord a, Num a, Scalar a) => Scalar (Position' a) where
|
|
|
|
|
scalar = fromIntegral . length . line (0, 0) . view _Position
|
|
|
|
|
fromScalar n = Position (fromScalar n) (fromScalar n)
|
2019-08-31 19:17:27 +02:00
|
|
|
|
|
|
|
|
|
data Positioned a where
|
|
|
|
|
Positioned :: Position -> a -> Positioned a
|
|
|
|
|
deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable, Generic)
|
|
|
|
|
deriving anyclass (CoArbitrary, Function)
|
2019-09-28 19:20:57 +02:00
|
|
|
|
type role Positioned representational
|
2019-08-31 19:17:27 +02:00
|
|
|
|
|
2019-09-15 19:00:28 +02:00
|
|
|
|
_Positioned :: Iso (Position, a) (Position, b) (Positioned a) (Positioned b)
|
|
|
|
|
_Positioned = iso hither yon
|
|
|
|
|
where
|
|
|
|
|
hither (pos, a) = Positioned pos a
|
|
|
|
|
yon (Positioned pos b) = (pos, b)
|
|
|
|
|
|
2019-08-31 19:17:27 +02:00
|
|
|
|
instance Arbitrary a => Arbitrary (Positioned a) where
|
|
|
|
|
arbitrary = Positioned <$> arbitrary <*> arbitrary
|
|
|
|
|
|
|
|
|
|
position :: Lens' (Positioned a) Position
|
|
|
|
|
position = lens
|
|
|
|
|
(\(Positioned pos _) -> pos)
|
|
|
|
|
(\(Positioned _ a) pos -> Positioned pos a)
|
|
|
|
|
|
|
|
|
|
positioned :: Lens (Positioned a) (Positioned b) a b
|
|
|
|
|
positioned = lens
|
|
|
|
|
(\(Positioned _ x') -> x')
|
|
|
|
|
(\(Positioned pos _) x' -> Positioned pos x')
|
|
|
|
|
|
|
|
|
|
loc :: Iso' Position Location
|
|
|
|
|
loc = iso hither yon
|
|
|
|
|
where
|
|
|
|
|
hither (Position px py) = Location (px, py)
|
|
|
|
|
yon (Location (lx, ly)) = Position lx ly
|
|
|
|
|
|
2019-10-13 18:37:08 +02:00
|
|
|
|
_Position :: Iso' (Position' a) (a, a)
|
2019-09-15 19:00:28 +02:00
|
|
|
|
_Position = iso hither yon
|
|
|
|
|
where
|
|
|
|
|
hither (Position px py) = (px, py)
|
|
|
|
|
yon (lx, ly) = Position lx ly
|
|
|
|
|
|
2019-10-13 18:37:08 +02:00
|
|
|
|
positionFromPair :: (Num a, Integral i, Integral j) => (i, j) -> Position' a
|
2019-09-13 21:24:05 +02:00
|
|
|
|
positionFromPair (i, j) = Position (fromIntegral i) (fromIntegral j)
|
|
|
|
|
|
2019-09-29 16:54:52 +02:00
|
|
|
|
-- | Add two positions
|
|
|
|
|
--
|
|
|
|
|
-- Operation for the additive group on positions
|
2019-10-13 18:37:08 +02:00
|
|
|
|
addPositions :: Num a => Position' a -> Position' a -> Position' a
|
2019-09-29 16:54:52 +02:00
|
|
|
|
addPositions = (<>)
|
|
|
|
|
|
|
|
|
|
-- | Subtract two positions.
|
|
|
|
|
--
|
|
|
|
|
-- diffPositions pos₁ pos₂ = pos₁ `addPositions` (invert pos₂)
|
2019-10-13 18:37:08 +02:00
|
|
|
|
diffPositions :: Num a => Position' a -> Position' a -> Position' a
|
2019-09-29 16:54:52 +02:00
|
|
|
|
diffPositions (Position x₁ y₁) (Position x₂ y₂) = Position (x₁ - x₂) (y₁ - y₂)
|
|
|
|
|
|
|
|
|
|
-- | Is this position a unit position? or: When taken as a difference, does this
|
|
|
|
|
-- position represent a step of one tile?
|
|
|
|
|
--
|
|
|
|
|
-- ∀ dir :: Direction. isUnit ('asPosition' dir)
|
2019-10-13 18:37:08 +02:00
|
|
|
|
isUnit :: (Eq a, Num a) => Position' a -> Bool
|
2019-10-06 19:13:00 +02:00
|
|
|
|
isUnit (Position px py) =
|
|
|
|
|
abs px `elem` [0,1] && abs py `elem` [0, 1] && (px, py) /= (0, 0)
|
2019-09-29 16:54:52 +02:00
|
|
|
|
|
2019-08-31 19:17:27 +02:00
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
2019-09-07 20:49:59 +02:00
|
|
|
|
data Dimensions' a = Dimensions
|
|
|
|
|
{ _width :: a
|
|
|
|
|
, _height :: a
|
|
|
|
|
}
|
|
|
|
|
deriving stock (Show, Eq, Functor, Generic)
|
|
|
|
|
deriving anyclass (CoArbitrary, Function)
|
|
|
|
|
makeFieldsNoPrefix ''Dimensions'
|
|
|
|
|
|
|
|
|
|
instance Arbitrary a => Arbitrary (Dimensions' a) where
|
|
|
|
|
arbitrary = Dimensions <$> arbitrary <*> arbitrary
|
|
|
|
|
|
|
|
|
|
type Dimensions = Dimensions' Word
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
2019-08-31 19:17:27 +02:00
|
|
|
|
data Direction where
|
|
|
|
|
Up :: Direction
|
|
|
|
|
Down :: Direction
|
|
|
|
|
Left :: Direction
|
|
|
|
|
Right :: Direction
|
|
|
|
|
UpLeft :: Direction
|
|
|
|
|
UpRight :: Direction
|
|
|
|
|
DownLeft :: Direction
|
|
|
|
|
DownRight :: Direction
|
2019-09-20 19:14:55 +02:00
|
|
|
|
Here :: Direction
|
2019-08-31 19:17:27 +02:00
|
|
|
|
deriving stock (Show, Eq, Generic)
|
|
|
|
|
|
|
|
|
|
instance Arbitrary Direction where
|
|
|
|
|
arbitrary = genericArbitrary
|
|
|
|
|
shrink = genericShrink
|
|
|
|
|
|
|
|
|
|
opposite :: Direction -> Direction
|
|
|
|
|
opposite Up = Down
|
|
|
|
|
opposite Down = Up
|
|
|
|
|
opposite Left = Right
|
|
|
|
|
opposite Right = Left
|
|
|
|
|
opposite UpLeft = DownRight
|
|
|
|
|
opposite UpRight = DownLeft
|
|
|
|
|
opposite DownLeft = UpRight
|
|
|
|
|
opposite DownRight = UpLeft
|
2019-09-20 19:14:55 +02:00
|
|
|
|
opposite Here = Here
|
2019-08-31 19:17:27 +02:00
|
|
|
|
|
|
|
|
|
move :: Direction -> Position -> Position
|
|
|
|
|
move Up = y -~ 1
|
|
|
|
|
move Down = y +~ 1
|
|
|
|
|
move Left = x -~ 1
|
|
|
|
|
move Right = x +~ 1
|
|
|
|
|
move UpLeft = move Up . move Left
|
|
|
|
|
move UpRight = move Up . move Right
|
|
|
|
|
move DownLeft = move Down . move Left
|
|
|
|
|
move DownRight = move Down . move Right
|
2019-09-20 19:14:55 +02:00
|
|
|
|
move Here = id
|
2019-08-31 19:17:27 +02:00
|
|
|
|
|
|
|
|
|
asPosition :: Direction -> Position
|
|
|
|
|
asPosition dir = move dir mempty
|
2019-09-02 19:56:25 +02:00
|
|
|
|
|
2019-09-29 16:54:52 +02:00
|
|
|
|
-- | Returns the direction that a given position is from a given source position
|
|
|
|
|
directionOf
|
|
|
|
|
:: Position -- ^ Source
|
|
|
|
|
-> Position -- ^ Target
|
|
|
|
|
-> Direction
|
|
|
|
|
directionOf (Position x₁ y₁) (Position x₂ y₂) =
|
|
|
|
|
case (x₁ `compare` x₂, y₁ `compare` y₂) of
|
|
|
|
|
(EQ, EQ) -> Here
|
|
|
|
|
(EQ, LT) -> Down
|
|
|
|
|
(EQ, GT) -> Up
|
|
|
|
|
(LT, EQ) -> Right
|
|
|
|
|
(GT, EQ) -> Left
|
|
|
|
|
|
|
|
|
|
(LT, LT) -> DownRight
|
|
|
|
|
(GT, LT) -> DownLeft
|
|
|
|
|
|
|
|
|
|
(LT, GT) -> UpRight
|
|
|
|
|
(GT, GT) -> UpLeft
|
|
|
|
|
|
|
|
|
|
-- | Take one (potentially diagonal) step towards the given position
|
|
|
|
|
--
|
|
|
|
|
-- ∀ src tgt. isUnit (src `diffPositions` (src `stepTowards tgt`))
|
|
|
|
|
stepTowards
|
|
|
|
|
:: Position -- ^ Source
|
|
|
|
|
-> Position -- ^ Target
|
|
|
|
|
-> Position
|
|
|
|
|
stepTowards (view _Position -> p₁) (view _Position -> p₂)
|
|
|
|
|
| p₁ == p₂ = _Position # p₁
|
|
|
|
|
| otherwise =
|
|
|
|
|
let (_:p:_) = line p₁ p₂
|
|
|
|
|
in _Position # p
|
|
|
|
|
|
2019-09-02 19:56:25 +02:00
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
2019-09-10 02:54:33 +02:00
|
|
|
|
data Neighbors a = Neighbors
|
|
|
|
|
{ _topLeft
|
|
|
|
|
, _top
|
|
|
|
|
, _topRight
|
|
|
|
|
, _left
|
|
|
|
|
, _right
|
|
|
|
|
, _bottomLeft
|
|
|
|
|
, _bottom
|
|
|
|
|
, _bottomRight :: a
|
2019-09-02 19:56:25 +02:00
|
|
|
|
}
|
2019-09-10 02:54:33 +02:00
|
|
|
|
deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable, Generic)
|
2019-09-02 19:56:25 +02:00
|
|
|
|
deriving anyclass (NFData)
|
2019-09-10 02:54:33 +02:00
|
|
|
|
makeLenses ''Neighbors
|
|
|
|
|
|
|
|
|
|
instance Applicative Neighbors where
|
|
|
|
|
pure α = Neighbors
|
|
|
|
|
{ _topLeft = α
|
|
|
|
|
, _top = α
|
|
|
|
|
, _topRight = α
|
|
|
|
|
, _left = α
|
|
|
|
|
, _right = α
|
|
|
|
|
, _bottomLeft = α
|
|
|
|
|
, _bottom = α
|
|
|
|
|
, _bottomRight = α
|
|
|
|
|
}
|
|
|
|
|
nf <*> nx = Neighbors
|
|
|
|
|
{ _topLeft = nf ^. topLeft $ nx ^. topLeft
|
|
|
|
|
, _top = nf ^. top $ nx ^. top
|
|
|
|
|
, _topRight = nf ^. topRight $ nx ^. topRight
|
|
|
|
|
, _left = nf ^. left $ nx ^. left
|
|
|
|
|
, _right = nf ^. right $ nx ^. right
|
|
|
|
|
, _bottomLeft = nf ^. bottomLeft $ nx ^. bottomLeft
|
|
|
|
|
, _bottom = nf ^. bottom $ nx ^. bottom
|
|
|
|
|
, _bottomRight = nf ^. bottomRight $ nx ^. bottomRight
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
edges :: Neighbors a -> Edges a
|
|
|
|
|
edges neighs = Edges
|
|
|
|
|
{ eTop = neighs ^. top
|
|
|
|
|
, eBottom = neighs ^. bottom
|
|
|
|
|
, eLeft = neighs ^. left
|
|
|
|
|
, eRight = neighs ^. right
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
neighborDirections :: Neighbors Direction
|
|
|
|
|
neighborDirections = Neighbors
|
|
|
|
|
{ _topLeft = UpLeft
|
|
|
|
|
, _top = Up
|
|
|
|
|
, _topRight = UpRight
|
|
|
|
|
, _left = Left
|
|
|
|
|
, _right = Right
|
|
|
|
|
, _bottomLeft = DownLeft
|
|
|
|
|
, _bottom = Down
|
|
|
|
|
, _bottomRight = DownRight
|
|
|
|
|
}
|
2019-09-02 19:56:25 +02:00
|
|
|
|
|
2019-09-10 02:54:33 +02:00
|
|
|
|
neighborPositions :: Position -> Neighbors Position
|
|
|
|
|
neighborPositions pos = (`move` pos) <$> neighborDirections
|
2019-09-29 16:54:52 +02:00
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
2019-10-13 18:37:08 +02:00
|
|
|
|
|
|
|
|
|
newtype Per a b = Rate Double
|
|
|
|
|
deriving stock (Show, Eq, Generic)
|
|
|
|
|
deriving anyclass (NFData, CoArbitrary, Function)
|
2019-11-16 03:20:01 +01:00
|
|
|
|
deriving (Num, Ord, Enum, Real, Fractional, ToJSON, FromJSON) via Double
|
2019-10-13 18:37:08 +02:00
|
|
|
|
deriving (Semigroup, Monoid) via Product Double
|
|
|
|
|
instance Arbitrary (Per a b) where arbitrary = genericArbitrary
|
|
|
|
|
|
|
|
|
|
invertRate :: a `Per` b -> b `Per` a
|
|
|
|
|
invertRate (Rate p) = Rate $ 1 / p
|
|
|
|
|
|
|
|
|
|
invertedRate :: Iso (a `Per` b) (b' `Per` a') (b `Per` a) (a' `Per` b')
|
|
|
|
|
invertedRate = iso invertRate invertRate
|
|
|
|
|
|
|
|
|
|
infixl 7 |*|
|
|
|
|
|
(|*|) :: (Scalar a, Scalar b) => a `Per` b -> b -> a
|
|
|
|
|
(|*|) (Rate rate) b = fromScalar $ rate * scalar b
|
|
|
|
|
|
|
|
|
|
newtype Ticks = Ticks Word
|
|
|
|
|
deriving stock (Show, Eq, Generic)
|
|
|
|
|
deriving anyclass (NFData, CoArbitrary, Function)
|
|
|
|
|
deriving (Num, Ord, Bounded, Enum, Integral, Real, ToJSON, FromJSON) via Word
|
|
|
|
|
deriving (Semigroup, Monoid) via (Sum Word)
|
|
|
|
|
deriving Scalar via ScalarIntegral Ticks
|
|
|
|
|
instance Arbitrary Ticks where arbitrary = genericArbitrary
|
|
|
|
|
|
|
|
|
|
newtype Tiles = Tiles Double
|
|
|
|
|
deriving stock (Show, Eq, Generic)
|
|
|
|
|
deriving anyclass (NFData, CoArbitrary, Function)
|
|
|
|
|
deriving (Num, Ord, Enum, Real, ToJSON, FromJSON, Scalar) via Double
|
|
|
|
|
deriving (Semigroup, Monoid) via (Sum Double)
|
|
|
|
|
instance Arbitrary Tiles where arbitrary = genericArbitrary
|
|
|
|
|
|
|
|
|
|
type TicksPerTile = Ticks `Per` Tiles
|
|
|
|
|
type TilesPerTick = Tiles `Per` Ticks
|
|
|
|
|
|
|
|
|
|
timesTiles :: TicksPerTile -> Tiles -> Ticks
|
|
|
|
|
timesTiles = (|*|)
|
2019-11-16 03:20:01 +01:00
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
newtype Hitpoints = Hitpoints Word
|
|
|
|
|
deriving stock (Show, Eq, Generic)
|
|
|
|
|
deriving anyclass (NFData, CoArbitrary, Function)
|
|
|
|
|
deriving (Arbitrary, Num, Ord, Bounded, Enum, Integral, Real, ToJSON, FromJSON)
|
|
|
|
|
via Word
|
|
|
|
|
deriving (Semigroup, Monoid) via Sum Word
|
|
|
|
|
|