packages feed

numerals-0.3: src/Text/Numeral/Language/PT.hs

{-# LANGUAGE NoImplicitPrelude
           , OverloadedStrings
           , PackageImports
           , UnicodeSyntax
  #-}

{-|
[@ISO639-1@]        pt

[@ISO639-2@]        por

[@ISO639-3@]        por

[@Native name@]     Português

[@English name@]    Portuguese
-}

module Text.Numeral.Language.PT
    ( cardinal
    , struct
    ) where

-------------------------------------------------------------------------------
-- Imports
-------------------------------------------------------------------------------

import "base" Data.Bool     ( otherwise )
import "base" Data.Function ( ($), const, fix )
import "base" Data.Maybe    ( Maybe(Just) )
import "base" Data.Monoid   ( Monoid )
import "base" Data.Ord      ( (<) )
import "base" Data.String   ( IsString )
import "base" Prelude       ( Integral, (-), Integer )
import "base-unicode-symbols" Data.Eq.Unicode       ( (≡) )
import "base-unicode-symbols" Data.Function.Unicode ( (∘) )
import "base-unicode-symbols" Data.Ord.Unicode      ( (≤) )
import qualified "containers" Data.Map as M ( fromList, lookup )
import           "numerals-base" Text.Numeral
import           "numerals-base" Text.Numeral.Misc ( dec )
import qualified "numerals-base" Text.Numeral.BigNum      as BN
import qualified "numerals-base" Text.Numeral.Exp.Classes as C


-------------------------------------------------------------------------------
-- PT
-------------------------------------------------------------------------------

-- Sources:
--   http://www.sonia-portuguese.com/text/numerals.htm
--   http://www.smartphrase.com/Portuguese/po_numbers_voc.shtml

cardinal ∷ (Integral α, C.Scale α, Monoid s, IsString s) ⇒ α → Maybe s
cardinal = cardinalRepr ∘ struct

struct ∷ ( Integral α, C.Scale α
         , C.Unknown β, C.Lit β, C.Neg β, C.Add β, C.Mul β, C.Scale β
         )
       ⇒ α → β
struct = pos $ fix $ rule `combine` shortScale R L BN.rule
    where
      rule = findRule (   0, lit       )
                    [ (  11, add 10 L  )
                    , (  16, add 10 R  )
                    , (  20, mul 10 R L)
                    , ( 100, step  100   10 R L)
                    , (1000, step 1000 1000 R L)
                    ]
                    (dec 6 - 1)

cardinalRepr ∷ (Monoid s, IsString s) ⇒ Exp → Maybe s
cardinalRepr = render defaultRepr
               { reprValue = \n → M.lookup n syms
               , reprScale = shortScaleRepr
               , reprAdd   = Just (⊞)
               , reprMul   = Just (⊡)
               , reprNeg   = Just $ \_ _ → "menos "
               }
    where
      (Lit 10 ⊞ Lit n ) _ | n < 8     = "as"
                          | n ≡ 8     = ""
                          | otherwise = "a"
      (Lit _  ⊞ Lit 10) _             = ""
      (_      ⊞ _     ) _             = " e "


      (_ ⊡ Lit 10 ) _ = ""
      (_ ⊡ Lit 100) _ = ""
      (_ ⊡ _      ) _ = " "

      syms =
          M.fromList
          [ (0, const "zero")
          , (1, \c → case c of
                       CtxAdd _ (Lit 10) _ → "on"
                       _                   → "um"
            )
          , (2, \c → case c of
                       CtxAdd _ (Lit 10)  _ → "do"
                       CtxMul _ (Lit 10)  _ → "vin"
                       CtxMul _ (Lit 100) _ → "duz"
                       _                    → "dois"
            )
          , (3, \c → case c of
                       CtxAdd _ (Lit 10)  _ → "tre"
                       CtxMul _ (Lit 10)  _ → "trin"
                       CtxMul _ (Lit 100) _ → "trez"
                       _                    → "três"
            )
          , (4, \c → case c of
                       CtxAdd _ (Lit 10)  _ → "cator"
                       CtxMul _ (Lit 10)  _ → "quaren"
                       _                    → "quatro"
            )
          , (5, \c → case c of
                       CtxAdd _ (Lit 10)  _ → "quin"
                       CtxMul _ (Lit 10)  _ → "cinquen"
                       CtxMul _ (Lit 100) _ → "quin"
                       _                    → "cinco"
            )
          , (6, \c → case c of
                       CtxMul _ (Lit 10) _ → "sessen"
                       _                   → "seis"
            )
          , (7, \c → case c of
                       CtxMul _ (Lit 10) _ → "seten"
                       _                   → "sete"
            )
          , (8, \c → case c of
                       CtxMul _ (Lit 10) _ → "oiten"
                       _                   → "oito"
            )
          , (9, \c → case c of
                       CtxMul _ (Lit 10) _ → "noven"
                       _                   → "nove"
            )
          , (10, \c → case c of
                        CtxAdd R (Lit _) _ → "ze"
                        CtxMul R (Lit 2) _ → "te"
                        CtxMul R (Lit _) _ → "ta"
                        _                  → "dez"
            )
          , (100, \c → case c of
                         CtxAdd {}       → "cento"
                         CtxMul _ (Lit n) _
                             | n ≤ 3     → "entos"
                             | n ≡ 4     → "centos"
                             | n ≡ 5     → "hentos"
                             | otherwise → "centos"
                         _               → "cem"
            )
          , (1000, const "mil")
          ]

shortScaleRepr ∷ (IsString s, Monoid s)
               ⇒ Integer → Integer → Exp → Ctx Exp → Maybe s
shortScaleRepr =
    BN.scaleRepr "ilhão" "ilhões"
                 [(4, BN.forms "quatr" "quator" "quator" "quatra" "quatri")]