ordinal-0.1.0.0: src/Text/Numerals/Languages/English.hs
{-# LANGUAGE OverloadedLists, OverloadedStrings, TemplateHaskell #-}
{-|
Module : Text.Numerals.Languages.English
Description : A module to convert numbers to words in the /English/ language.
Maintainer : hapytexeu+gh@gmail.com
Stability : experimental
Portability : POSIX
This module contains logic to convert numbers to words in the /English/ language.
-}
module Text.Numerals.Languages.English (
-- * Num to word algorithm
english
-- * Convert to ordinal
, ordinize'
-- * Constant words
, negativeWord', zeroWord', oneWord'
-- * Names for numbers
, lowWords', midWords', highWords'
-- * Merge function
, merge'
) where
import Data.Text(Text, isSuffixOf)
import qualified Data.Text as T
import Data.Vector(Vector)
import Text.Numerals.Algorithm(HighNumberAlgorithm(ShortScale), NumeralsAlgorithm, numeralsAlgorithm)
import Text.Numerals.Algorithm.Template(ordinizeFromDict)
import Text.Numerals.Class(valueSplit)
import Text.Numerals.Internal(_mergeWith, _mergeWithSpace, _mergeWithHyphen)
_ordinizepp :: Text -> Text
_ordinizepp t
| "y" `isSuffixOf` t = T.init t <> "ieth"
| otherwise = t <> "th"
-- | A function that converts a number in words in /cardinal/ form to /ordinal/
-- form according to the /English/ language rules.
$(pure [ordinizeFromDict "ordinize'" [
("one", "first")
, ("two", "second")
, ("three", "third")
, ("four", "fourth")
, ("five", "fifth")
, ("six", "sixth")
, ("seven", "seventh")
, ("eight", "eighth")
, ("nine", "ninth")
, ("ten", "tenth")
, ("eleven", "eleventh")
, ("twelve", "twelfth")
] '_ordinizepp])
-- | A 'NumeralsAlgorithm' to convert numbers to words in the /English/ language.
english :: NumeralsAlgorithm -- ^ A 'NumeralsAlgorithm' that can be used to convert numbers to different formats.
english = numeralsAlgorithm negativeWord' zeroWord' oneWord' lowWords' midWords' (valueSplit highWords') merge' ordinize'
-- | The words used to mark a negative number in the /English/ language.
negativeWord' :: Text
negativeWord' = "minus"
-- | The word used for the number /zero/ in the /English/ language.
zeroWord' :: Text
zeroWord' = "zero"
-- | The word used for the number /one/ in the /English/ language.
oneWord' :: Text
oneWord' = "one"
-- | A 'Vector' that contains the word used for the numbers /two/ to /twenty/ in the /English/ language.
lowWords' :: Vector Text
lowWords' = [
"two"
, "three"
, "four"
, "five"
, "six"
, "seven"
, "eight"
, "nine"
, "ten"
, "eleven"
, "twelve"
, "thirteen"
, "fourteen"
, "fifteen"
, "sixteen"
, "seventeen"
, "eighteen"
, "nineteen"
, "twenty"
]
-- | A list of 2-tuples that contains the names of values between /thirty/ and
-- /thousand/ in the /English/ language.
midWords' :: [(Integer, Text)]
midWords' = [
(1000, "thousand")
, (100, "hundred")
, (90, "ninety")
, (80, "eighty")
, (70, "seventy")
, (60, "sixty")
, (50, "fifty")
, (40, "forty")
, (30, "thirty")
]
-- | A merge function that is used to combine the names of words together to
-- larger words, according to the /English/ grammar rules.
merge' :: Integral i => i -> i -> Text -> Text -> Text
merge' 1 r | r < 100 = const id
merge' l r | 100 > l && l > r = _mergeWithHyphen
| l >= 100 && 100 > r = _mergeWith " and "
| r > l = _mergeWithSpace
merge' _ _ = _mergeWith ", "
-- | An algorithm to obtain the names of /large/ numbers (one million or larger)
-- in /English/. English uses a /short scale/ with the @illion@ suffix.
highWords' :: HighNumberAlgorithm
highWords' = ShortScale "illion"