numhask: A numeric class hierarchy.

[ bsd3, library, math ] [ Propose Tags ]

This package provides alternative numeric classes over Prelude.

The numeric class constellation looks somewhat like:


>>> {-# LANGUAGE GHC2021 #-}
>>> {-# LANGUAGE RebindableSyntax #-}
>>> import NumHask.Prelude

See NumHask for a detailed overview.

[Skip to Readme]


Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


Versions [RSS] 0.0.1, 0.0.2, 0.0.3, 0.0.4, 0.0.5, 0.0.6, 0.0.7, 0.0.8, 0.0.9, 0.1.0, 0.1.1, 0.1.2, 0.1.3,,,,,,,, 0.3.1, 0.4.0, 0.5.0, 0.6.0,,,,,,,,,,,,,,,,
Change log
Dependencies base (>=4.7 && <5), QuickCheck (>=2.14 && <2.15) [details]
License BSD-3-Clause
Copyright Tony Day (c) 2016
Author Tony Day
Category math
Home page
Bug tracker
Source repo head: git clone
Uploaded by tonyday567 at 2024-02-12T01:58:19Z
Distributions LTSHaskell:, NixOS:, Stackage:
Reverse Dependencies 24 direct, 6 indirect [details]
Downloads 15483 total (121 in the last 30 days)
Rating 2.25 (votes: 2) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2024-02-12 [all 1 reports]

Readme for numhask-

[back to package description]


Hackage Build Status


{-# LANGUAGE RebindableSyntax #-}
import NumHask.Prelude

See the documentation in the NumHask module for a detailed overview.

v0.12 notes


Compared to previous library versions, Ring and Field have been removed as super classes of QuotientField, and SemiField introduced as the new constraint.

Old version:

type SemiField a = (Distributive a, Divisive a)

class (SemiField a) => QuotientField a where
  type Whole a :: Type
  properFraction :: a -> (Whole a, a)

The notion of a quotient is now that which distributes and divides.

Subtractive originally slipped in as a super class due to the notion of rounding down (or, specifically, towards zero). By using DefaultSignatures, a default for Subtractive-type numbers can be provided and still allow non-Subtractive (SemiField) things to be quotient fields.

Infinity and nan move from a Field to a SemiField constraint - subtraction is not needed to come up with an infinity or silly compute.


A motivation for SemiField was to introduce NumHask.Data.Positive into the library. Positive has no sane Subtractive instance (but should be able to be rounded).

Out of the many approaches that can be taken in defining a positive number, the definition relies on a notion of truncated subtraction; that subtraction can be performed on positive numbers but, for answers outside the typed range, the lower bound should be returned.

Specifically, the positive constructor needs to be supplied with a number that has a MeetSemiLattice instance, so that complex numbers and other geometries are correctly handled:

ghci> 2 +: (-2)
Complex {complexPair = (2,-2)}
ghci> positive (2 +: (-2))
UnsafePositive {unPositive = Complex {complexPair = (2,0)}}

Truncated Arithmetic

Truncated subtraction can be generalised to a notion of truncated arithmetic on a number with a typed range. This may be a direction explored further in the library including:

  • [epsilon, +infinity): A positive number type which is a safe divisor.
  • /= zero, non-zero arithmetic (x - x returns epsilon, say)
  • [0,1]: probability and weight arithmetic
  • [-1,1]: correlation math

magnitudes are positive

The current Basis instance of Double:

instance Basis Double where
  type Mag Double = Double
  type Base Double = Double
  magnitude = P.abs
  basis = P.signum

is probably more correctly written as:

instance Basis Double where
  type Mag Double = Positive Double
  type Base Double = Sign Double
  magnitude = Positive . P.abs
  basis = Sign . P.signum

where Sign is a future-imagined type representing {-1,0,1} or {-1,1}

In Haskell, there is a basic choice between using multiple parameters for a type or embedding types using type families. Using multiple parameters would, in practice, force users to have to chose and write 'Basis Double Double Double' or 'Basis Positive Sign Double'.

On balance, a computational chain involving magnitude is likely to be a single, underlying type, so that providing a Basis instance returning a Positive would result in a lot of unwrapping.

-- endo-based
x == basis x * magnitude x

-- if hetero-typed ...
x == (unSign $ basis x) * (unPositive $ magnitude x)

The library awaits real-world feedback on safety versus ergonomics.


Truncated subtraction is encapsulated within the Monus class and supplied operator:

ghci> 4 ∸ 7 :: Positive Int
UnsafePositive {unPositive = 0}
ghci> unPositive (4 ∸ 7 :: Positive Int)
ghci> unPositive (7 ∸ 4 :: Positive Int)


The introduction of Positive provoked including a wrapper type for most numhask types. This type can be used with derivingvia:

newtype Positive a = UnsafePositive {unPositive :: a}
  deriving stock
    (Eq, Ord, Show)
    ( Additive,
    via (Wrapped a)