Introduction
We give examples of common uses of the types and functions defined in plutus-numeric, as well as some explanations for how to do ‘typical’ tasks. In particular, we cover use of:
-
Natural(fromPlutusTx.Natural) -
NatRatio(fromPlutusTx.NatRatio)
Construction
Compile-time constants
To create values known at compile-time, use the quasi-quoters provided in PlutusTx.Natural and PlutusTx.NatRatio. For Natural, there is one quasi-quoter:
{-# LANGUAGE QuasiQuotes #-}
module Example.Natural where
import PlutusTx.Natural (Natural, nat)
lifeTheUniverseAndEverything :: Natural
lifeTheUniverseAndEverything = [nat | 42 |]
-- You can use underscore as a separator
billion :: Natural
billion = [nat| 1_000_000_000 |]
For NatRatio, there are two quasi-quoters:
{-# LANGUAGE QuasiQuotes #-}
module Example.NatRatio where
import PlutusTx.NatRatio (NatRatio, dec, frac)
-- frac uses a numerator-denominator pair
oneHalf :: NatRatio
oneHalf = [frac| (1, 2) |]
-- dec uses a decimal
oneHundredth :: NatRatio
oneHundredth = [dec| 0.01 |]
Lastly, both Natural and NatRatio are instances of both AdditiveMonoid and MultiplicativeMonoid; thus, zero and one will work for both of them, in the expected manner.
Runtime values
For values only known at runtime, you can convert from Integer or Rational; see the ‘Conversion’ section for how to do this. For NatRatio specifically, there is also a way of construction using two Naturals:
module NatRatio.Example where
import PlutusTx.NatRatio (NatRatio, natRatio)
import PlutusTx.Natural (Natural)
numerator :: Natural
numerator = -- something
denominator :: Natural
denominator = -- something else
myRatio :: Maybe NatRatio
myRatio = natRatio numerator denominator -- will be Nothing if denominator is zeroConversion
As both Natural and NatRatio are instances of IntegralDomain, there is a range of ways that conversions to, and from, base Plutus types, available.
{-# LANGUAGE QuasiQuotes #-}
module Conversions.Example where
import PlutusTx.Natural (Natural, nat)
import PlutusTx.NatRatio (NatRatio, dec)
import PlutusTx.Numeric (addExtend, projectAbs, restrictMay)
import PlutusTx.Ratio (Ratio)
import qualified PlutusTx.Ratio as Ratio
-- Most general method, returns in a Maybe.
outOfInteger :: Maybe Natural
outOfInteger = restrictMay 1234 -- will give a Just
outOfNegativeInteger :: Maybe Natural
outOfNegativeInteger = restrictMay (-1234) -- will give Nothing
outOfRational :: Maybe NatRatio
outOfRational = restrictMay (1 Ratio.% 2) -- will give a Just
outOfNegativeRational :: Maybe NatRatio
outOfNegativeRational = restrictMay ((-1) Ratio.% 2) -- will give Nothing
-- 'Clamping' method, producing the absolute value of what it's given.
outOfIntegerAbs :: Natural
outOfIntegerAbs = projectAbs 1234 -- will give the same as [nat| 1234 |]
outOfNegativeIntegerAbs :: Natural
outOfNegativeIntegerAbs = projectAbs (-1234) -- will also give the same as [nat| 1234 |]
outOfRationalAbs :: NatRatio
outOfRationalAbs = projectAbs (1 Ratio.% 2) -- will give the same as [dec| 0.5 |]
outOfNegativeRationalAbs :: NatRatio
outOfNegativeRationalAbs = projectAbs ((-1) Ratio.% 2) -- will also give the same as [dec| 0.5 |]
-- 'Relaxes' a positive-only type into the same value in its possibly-negative counterpart
relaxNatural :: Integer
relaxNatural = addExtend [nat | 1234 |] -- same as 1234
relaxNatRatio :: Rational
relaxNatRatio = addExtend [dec | 0.2 |] -- same as 2 Ratio.% 10
Operations
As both Natural and NatRatio are instances of both AdditiveSemigroup and MultiplicativeSemigroup, + and * will work as expected. Subtraction, however, can’t be defined on either type: instead, we provide a monus operation, which works similarly. For both Natural and NatRatio, monus (written ^-) is a ‘difference or zero’ operator:
{-# LANGUAGE QuasiQuotes #-}
module Monus.Example where
import Plutus.Numeric.Extra ((^-))
import Plutus.Natural (Natural, nat)
import Plutus.NatRatio (NatRatio, dec)
thisWillBeZero :: Natural
thisWillBeZero = [nat| 1 |] ^- [nat| 15 |]
thisWillNotBeZero :: Natural
thisWillNotBeZero = [nat| 15 |] ^- [nat| 1 |] -- will be the same as [nat| 14 |]
thisWillAlsoBeZero :: NatRatio
thisWillAlsoBeZero = [dec| 0.5 |] ^- [dec| 1.5 |]
butThisWillNot :: NatRatio
butThisWillNot = [dec| 1.5 |] ^- [dec| 0.5 |] -- will be the same as [dec| 0.5 |]
The laws that the monus operation follows are slightly different to those that subtraction would: check the documentation for the AdditiveHemigroup type class in PlutusTx.Numeric.Extra for details.