diff --git a/.stylish-haskell.yaml b/.stylish-haskell.yaml index 82d0aef..740e848 100644 --- a/.stylish-haskell.yaml +++ b/.stylish-haskell.yaml @@ -1,6 +1,8 @@ --- columns: 100 language_extensions: + - BangPatterns + - DefaultSignatures - DataKinds - DeriveDataTypeable - DeriveFunctor diff --git a/CHANGELOG.md b/CHANGELOG.md index b92b1f1..094d904 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,17 @@ # Changelog +## v3.0.0.0 (2018-03-13) + +- Review Currency strictness +- Add deepseq's NFData instance for Currency & Alpha +- Manually write Show & Read instance for Alpha (compile-time & performance gain) +- Remove currency constructors in favor of helper `fromAlpha` +- Add property tests to verify various instances + + ## v2.0.0.0 (2017-09-11) -Remove Swagger instances. It would be better to push them upstream to the swagger2 repository. +- Remove Swagger instances. It would be better to push them upstream to the swagger2 repository. ## v1.0.0.0 (2017-08-29) diff --git a/currency-codes.cabal b/currency-codes.cabal index 5f5a90c..e719e7c 100644 --- a/currency-codes.cabal +++ b/currency-codes.cabal @@ -1,11 +1,11 @@ name: currency-codes -version: 2.0.0.0 +version: 3.0.0.0 synopsis: ISO-4217 Currency Codes description: ISO-4217 Currency Codes license: MIT license-file: LICENSE author: Chordify -maintainer: Matthias Benkort +maintainer: Matthias Benkort copyright: (c) 2017 Chordify category: Data build-type: Simple @@ -15,30 +15,69 @@ extra-source-files: README.md CHANGELOG.md stack.yaml Setup.hs + .stylish-haskell.yaml cabal-version: >=1.10 library hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall - default-extensions: DataKinds - , DeriveDataTypeable - , DeriveFunctor - , DeriveGeneric - , ExistentialQuantification - , FlexibleContexts - , GADTs - , GeneralizedNewtypeDeriving - , MultiParamTypeClasses - , OverloadedStrings - , RecordWildCards - , ScopedTypeVariables - , TupleSections - , TypeOperators + default-extensions: BangPatterns + , DefaultSignatures + , DataKinds + , DeriveDataTypeable + , DeriveFunctor + , DeriveGeneric + , ExistentialQuantification + , FlexibleContexts + , GADTs + , GeneralizedNewtypeDeriving + , MultiParamTypeClasses + , OverloadedStrings + , RecordWildCards + , ScopedTypeVariables + , TupleSections + , TypeOperators + build-depends: base >= 4 && < 5 , aeson >= 0.7.0.0 , bson >= 0.2.0 + , deepseq , random >= 1.0.0.0 , safe >= 0.2 , text >= 1.0.0.0 + exposed-modules: Data.Currency + + +test-suite currency-codes-test + hs-source-dirs: test + main-is: Spec.hs + type: exitcode-stdio-1.0 + default-language: Haskell2010 + ghc-options: -Wall + default-extensions: BangPatterns + , DefaultSignatures + , DataKinds + , DeriveDataTypeable + , DeriveFunctor + , DeriveGeneric + , ExistentialQuantification + , FlexibleContexts + , GADTs + , GeneralizedNewtypeDeriving + , MultiParamTypeClasses + , OverloadedStrings + , RecordWildCards + , ScopedTypeVariables + , TupleSections + , TypeOperators + + build-depends: base + , currency-codes + , QuickCheck + , aeson + , bson + , hspec + + other-modules: Data.CurrencySpec diff --git a/src/Data/Currency.hs b/src/Data/Currency.hs index 387fc73..158eab4 100644 --- a/src/Data/Currency.hs +++ b/src/Data/Currency.hs @@ -1,60 +1,88 @@ -- | A Currency representation as specified in the ISO-4217 standard -module Data.Currency where - -import Prelude hiding (Ordering (..)) - -import Control.Monad ((>=>)) -import Data.Aeson as Aeson -import Data.Aeson (FromJSON (..), ToJSON (..)) -import Data.Bson (Val (..), (=:)) -import qualified Data.Bson as Bson -import Data.Data (Data) -import Data.Text (Text) -import Data.Typeable (Typeable) -import GHC.Generics (Generic) +module Data.Currency + -- * Types + ( Currency(..) + , Alpha(..) + , currencies + + -- * Create utilities + , fromAlpha + ) where + +import Prelude hiding (Ordering (..)) + +import Control.DeepSeq (NFData) +import Control.Monad ((>=>)) +import Data.Aeson (FromJSON (..), ToJSON (..)) +import Data.Bson (Val (..), (=:)) +import Data.Data (Data, dataTypeConstrs, dataTypeOf, toConstr) +import Data.List (elemIndex) +import Data.Text (Text) +import Data.Typeable (Typeable) +import GHC.Generics (Generic) +import System.Random (Random (..)) + +import qualified Data.Aeson as Aeson +import qualified Data.Bson as Bson import qualified Safe -import System.Random (Random (..)) -- | Actual representation of a currency data Currency = Currency - { alpha :: Alpha -- ^ Alpha Code - , numeric :: Int -- ^ Numeric code - , minor :: Int -- ^ Number of decimal units - , name :: Text -- ^ English name + { alpha :: !Alpha -- ^ Alpha Code + , numeric :: !Int -- ^ Numeric code + , minor :: !Int -- ^ Number of decimal units + , name :: !Text -- ^ English name } deriving (Show, Eq, Read, Generic, Data, Typeable) -instance FromJSON Currency where parseJSON = Aeson.genericParseJSON Aeson.defaultOptions -instance ToJSON Currency where toJSON = Aeson.genericToJSON Aeson.defaultOptions +instance NFData Currency + + +instance FromJSON Currency where + parseJSON = + Aeson.genericParseJSON Aeson.defaultOptions + + +instance ToJSON Currency where + toJSON = + Aeson.genericToJSON Aeson.defaultOptions + instance Val Currency where val Currency{..} = Bson.Doc - [ "alpha" =: alpha - , "numeric" =: numeric - , "minor" =: minor + [ "alpha" =: alpha + , "numeric" =: numeric + , "minor" =: minor , "name" =: name ] - cast' v = case v of - Bson.Doc doc -> Currency - <$> Bson.lookup "alpha" doc - <*> Bson.lookup "numeric" doc - <*> Bson.lookup "minor" doc - <*> Bson.lookup "name" doc + cast' = cast' >=> \doc -> Currency + <$> Bson.lookup "alpha" doc + <*> Bson.lookup "numeric" doc + <*> Bson.lookup "minor" doc + <*> Bson.lookup "name" doc - _ -> Nothing instance Random Currency where random g = - let (i, g') = randomR (0, length currencies - 1) g - in (currencies !! i, g') + let + (i, g') = + randomR (0, length currencies - 1) g + in + (currencies !! i, g') randomR (a, b) g = - let currencies' = dropWhile (/= a) $ takeWhile (/= b) currencies - (i, g') = randomR (0, length currencies' - 1) g - in (currencies' !! i, g') + let + currencies' = + dropWhile (/= a) $ takeWhile (/= b) currencies + + (i, g') = + randomR (0, length currencies' - 1) g + in + (currencies' !! i, g') + -- | A type which represents ISO 4217 alphabetic codes as an enum data Alpha @@ -236,917 +264,257 @@ data Alpha | ZAR -- ^ Rand | ZMW -- ^ Zambian Kwacha | ZWL -- ^ Zimbabwe Dollar - deriving (Show, Eq, Ord, Enum, Bounded, Read, Generic, Data, Typeable) - -instance FromJSON Alpha where parseJSON = Aeson.genericParseJSON Aeson.defaultOptions - -instance ToJSON Alpha where toJSON = Aeson.genericToJSON Aeson.defaultOptions - -instance Val Alpha where val = val . show - cast' = cast' >=> Safe.readMay - -instance Random Alpha where - random g = - let (r, g') = randomR (fromEnum (minBound :: Alpha), fromEnum(maxBound :: Alpha)) g - in (toEnum r, g') - - randomR (l, h) g = - let (r, g') = randomR (fromEnum l, fromEnum h) g - in (toEnum r, g') - --- Constructor for all currencies - -unitOfAccount :: Currency -unitOfAccount = - Currency XUA 965 0 "ADB Unit of Account" - -afghani :: Currency -afghani = - Currency AFN 971 2 "Afghani" - -algerianDinar :: Currency -algerianDinar = - Currency DZD 012 2 "Algerian Dinar" - -argentinePeso :: Currency -argentinePeso = - Currency ARS 032 2 "Argentine Peso" - -armenianDram :: Currency -armenianDram = - Currency AMD 051 2 "Armenian Dram" - -arubanFlorin :: Currency -arubanFlorin = - Currency AWG 533 2 "Aruban Florin" - -australianDollar :: Currency -australianDollar = - Currency AUD 036 2 "Australian Dollar" - -azerbaijanManat :: Currency -azerbaijanManat = - Currency AZN 944 2 "Azerbaijan Manat" - -bahamianDollar :: Currency -bahamianDollar = - Currency BSD 044 2 "Bahamian Dollar" - -bahrainiDinar :: Currency -bahrainiDinar = - Currency BHD 048 3 "Bahraini Dinar" - -baht :: Currency -baht = - Currency THB 764 2 "Baht" - -balboa :: Currency -balboa = - Currency PAB 590 2 "Balboa" - -barbadosDollar :: Currency -barbadosDollar = - Currency BBD 052 2 "Barbados Dollar" - -belarusianRuble :: Currency -belarusianRuble = - Currency BYN 933 2 "Belarusian Ruble" - -belizeDollar :: Currency -belizeDollar = - Currency BZD 084 2 "Belize Dollar" - -bermudianDollar :: Currency -bermudianDollar = - Currency BMD 060 2 "Bermudian Dollar" - -boliviano :: Currency -boliviano = - Currency BOB 068 2 "Boliviano" - -bolívar :: Currency -bolívar = - Currency VEF 937 2 "Bolívar" - -bondMarketsCompositeUnit :: Currency -bondMarketsCompositeUnit = - Currency XBA 955 0 "Bond Markets Unit European Composite Unit (EURCO)" - -bondMarketsMonetaryUnit :: Currency -bondMarketsMonetaryUnit = - Currency XBB 956 0 "Bond Markets Unit European Monetary Unit (E.M.U.-6)" - -bondMarketsUnitofAccount17 :: Currency -bondMarketsUnitofAccount17 = - Currency XBD 958 0 "Bond Markets Unit European Unit of Account 17 (E.U.A.-17)" - -bondMarketsUnitofAccount9 :: Currency -bondMarketsUnitofAccount9 = - Currency XBC 957 0 "Bond Markets Unit European Unit of Account 9 (E.U.A.-9)" - -brazilianReal :: Currency -brazilianReal = - Currency BRL 986 2 "Brazilian Real" - -bruneiDollar :: Currency -bruneiDollar = - Currency BND 096 2 "Brunei Dollar" - -bulgarianLev :: Currency -bulgarianLev = - Currency BGN 975 2 "Bulgarian Lev" - -burundiFranc :: Currency -burundiFranc = - Currency BIF 108 0 "Burundi Franc" - -cfaFrancBCEAO :: Currency -cfaFrancBCEAO = - Currency XOF 952 0 "CFA Franc BCEAO" - -cfaFrancBEAC :: Currency -cfaFrancBEAC = - Currency XAF 950 0 "CFA Franc BEAC" - -cfpFranc :: Currency -cfpFranc = - Currency XPF 953 0 "CFP Franc" - -caboVerdeEscudo :: Currency -caboVerdeEscudo = - Currency CVE 132 2 "Cabo Verde Escudo" - -canadianDollar :: Currency -canadianDollar = - Currency CAD 124 2 "Canadian Dollar" - -caymanIslandsDollar :: Currency -caymanIslandsDollar = - Currency KYD 136 2 "Cayman Islands Dollar" - -chileanPeso :: Currency -chileanPeso = - Currency CLP 152 0 "Chilean Peso" - -testing :: Currency -testing = - Currency XTS 963 0 "Codes specifically reserved for testing purposes" - -colombianPeso :: Currency -colombianPeso = - Currency COP 170 2 "Colombian Peso" - -comorianFranc :: Currency -comorianFranc = - Currency KMF 174 0 "Comorian Franc" - -congoleseFranc :: Currency -congoleseFranc = - Currency CDF 976 2 "Congolese Franc" - -convertibleMark :: Currency -convertibleMark = - Currency BAM 977 2 "Convertible Mark" - -cordobaOro :: Currency -cordobaOro = - Currency NIO 558 2 "Cordoba Oro" - -costaRicanColon :: Currency -costaRicanColon = - Currency CRC 188 2 "Costa Rican Colon" - -cubanPeso :: Currency -cubanPeso = - Currency CUP 192 2 "Cuban Peso" - -czechKoruna :: Currency -czechKoruna = - Currency CZK 203 2 "Czech Koruna" - -dalasi :: Currency -dalasi = - Currency GMD 270 2 "Dalasi" - -danishKrone :: Currency -danishKrone = - Currency DKK 208 2 "Danish Krone" - -denar :: Currency -denar = - Currency MKD 807 2 "Denar" - -djiboutiFranc :: Currency -djiboutiFranc = - Currency DJF 262 0 "Djibouti Franc" - -dobra :: Currency -dobra = - Currency STD 678 2 "Dobra" - -dominicanPeso :: Currency -dominicanPeso = - Currency DOP 214 2 "Dominican Peso" - -dong :: Currency -dong = - Currency VND 704 0 "Dong" - -eastCaribbeanDollar :: Currency -eastCaribbeanDollar = - Currency XCD 951 2 "East Caribbean Dollar" - -egyptianPound :: Currency -egyptianPound = - Currency EGP 818 2 "Egyptian Pound" - -elSalvadorColon :: Currency -elSalvadorColon = - Currency SVC 222 2 "El Salvador Colon" - -ethiopianBirr :: Currency -ethiopianBirr = - Currency ETB 230 2 "Ethiopian Birr" - -euro :: Currency -euro = - Currency EUR 978 2 "Euro" - -falklandIslandsPound :: Currency -falklandIslandsPound = - Currency FKP 238 2 "Falkland Islands Pound" - -fijiDollar :: Currency -fijiDollar = - Currency FJD 242 2 "Fiji Dollar" - -forint :: Currency -forint = - Currency HUF 348 2 "Forint" - -ghanaCedi :: Currency -ghanaCedi = - Currency GHS 936 2 "Ghana Cedi" - -gibraltarPound :: Currency -gibraltarPound = - Currency GIP 292 2 "Gibraltar Pound" - -gold :: Currency -gold = - Currency XAU 959 0 "Gold" - -gourde :: Currency -gourde = - Currency HTG 332 2 "Gourde" - -guarani :: Currency -guarani = - Currency PYG 600 0 "Guarani" - -guineanFranc :: Currency -guineanFranc = - Currency GNF 324 0 "Guinean Franc" - -guyanaDollar :: Currency -guyanaDollar = - Currency GYD 328 2 "Guyana Dollar" - -hongKongDollar :: Currency -hongKongDollar = - Currency HKD 344 2 "Hong Kong Dollar" - -hryvnia :: Currency -hryvnia = - Currency UAH 980 2 "Hryvnia" - -icelandKrona :: Currency -icelandKrona = - Currency ISK 352 0 "Iceland Krona" - -indianRupee :: Currency -indianRupee = - Currency INR 356 2 "Indian Rupee" - -iranianRial :: Currency -iranianRial = - Currency IRR 364 2 "Iranian Rial" - -iraqiDinar :: Currency -iraqiDinar = - Currency IQD 368 3 "Iraqi Dinar" - -jamaicanDollar :: Currency -jamaicanDollar = - Currency JMD 388 2 "Jamaican Dollar" - -jordanianDinar :: Currency -jordanianDinar = - Currency JOD 400 3 "Jordanian Dinar" - -kenyanShilling :: Currency -kenyanShilling = - Currency KES 404 2 "Kenyan Shilling" - -kina :: Currency -kina = - Currency PGK 598 2 "Kina" + deriving (Eq, Ord, Enum, Bounded, Generic, Data, Typeable) -kuna :: Currency -kuna = - Currency HRK 191 2 "Kuna" -kuwaitiDinar :: Currency -kuwaitiDinar = - Currency KWD 414 3 "Kuwaiti Dinar" +instance NFData Alpha -kwanza :: Currency -kwanza = - Currency AOA 973 2 "Kwanza" -kyat :: Currency -kyat = - Currency MMK 104 2 "Kyat" +instance Show Alpha where + show = + show . toConstr -laoKip :: Currency -laoKip = - Currency LAK 418 2 "Lao Kip" -lari :: Currency -lari = - Currency GEL 981 2 "Lari" +instance Read Alpha where + readsPrec _ str = + let + (α, rest) = splitAt 3 (dropWhile (== ' ') str) + in + case elemIndex α alphas of + Just i -> + [(toEnum i, rest)] -lebanesePound :: Currency -lebanesePound = - Currency LBP 422 2 "Lebanese Pound" + Nothing -> + [] -lek :: Currency -lek = - Currency ALL 008 2 "Lek" -lempira :: Currency -lempira = - Currency HNL 340 2 "Lempira" +instance FromJSON Alpha where + parseJSON = + Aeson.genericParseJSON Aeson.defaultOptions -leone :: Currency -leone = - Currency SLL 694 2 "Leone" -liberianDollar :: Currency -liberianDollar = - Currency LRD 430 2 "Liberian Dollar" +instance ToJSON Alpha where + toJSON = + Aeson.genericToJSON Aeson.defaultOptions -libyanDinar :: Currency -libyanDinar = - Currency LYD 434 3 "Libyan Dinar" -lilangeni :: Currency -lilangeni = - Currency SZL 748 2 "Lilangeni" +instance Val Alpha where + val = + val . show -loti :: Currency -loti = - Currency LSL 426 2 "Loti" + cast' = + cast' >=> Safe.readMay -malagasyAriary :: Currency -malagasyAriary = - Currency MGA 969 2 "Malagasy Ariary" -malawiKwacha :: Currency -malawiKwacha = - Currency MWK 454 2 "Malawi Kwacha" - -malaysianRinggit :: Currency -malaysianRinggit = - Currency MYR 458 2 "Malaysian Ringgit" - -mauritiusRupee :: Currency -mauritiusRupee = - Currency MUR 480 2 "Mauritius Rupee" - -mexicanPeso :: Currency -mexicanPeso = - Currency MXN 484 2 "Mexican Peso" - -mexicanUnidadDeInversion :: Currency -mexicanUnidadDeInversion = - Currency MXV 979 2 "Mexican Unidad de Inversion (UDI)" - -moldovanLeu :: Currency -moldovanLeu = - Currency MDL 498 2 "Moldovan Leu" - -moroccanDirham :: Currency -moroccanDirham = - Currency MAD 504 2 "Moroccan Dirham" - -mozambiqueMetical :: Currency -mozambiqueMetical = - Currency MZN 943 2 "Mozambique Metical" - -mvdol :: Currency -mvdol = - Currency BOV 984 2 "Mvdol" - -naira :: Currency -naira = - Currency NGN 566 2 "Naira" - -nakfa :: Currency -nakfa = - Currency ERN 232 2 "Nakfa" - -namibiaDollar :: Currency -namibiaDollar = - Currency NAD 516 2 "Namibia Dollar" - -nepaleseRupee :: Currency -nepaleseRupee = - Currency NPR 524 2 "Nepalese Rupee" - -netherlandsAntilleanGuilder :: Currency -netherlandsAntilleanGuilder = - Currency ANG 532 2 "Netherlands Antillean Guilder" - -newIsraeliSheqel :: Currency -newIsraeliSheqel = - Currency ILS 376 2 "New Israeli Sheqel" - -newTaiwanDollar :: Currency -newTaiwanDollar = - Currency TWD 901 2 "New Taiwan Dollar" - -newZealandDollar :: Currency -newZealandDollar = - Currency NZD 554 2 "New Zealand Dollar" - -ngultrum :: Currency -ngultrum = - Currency BTN 064 2 "Ngultrum" - -northKoreanWon :: Currency -northKoreanWon = - Currency KPW 408 2 "North Korean Won" - -norwegianKrone :: Currency -norwegianKrone = - Currency NOK 578 2 "Norwegian Krone" - -ouguiya :: Currency -ouguiya = - Currency MRO 478 2 "Ouguiya" - -pakistanRupee :: Currency -pakistanRupee = - Currency PKR 586 2 "Pakistan Rupee" - -palladium :: Currency -palladium = - Currency XPD 964 0 "Palladium" - -pataca :: Currency -pataca = - Currency MOP 446 2 "Pataca" - -paanga :: Currency -paanga = - Currency TOP 776 2 "Pa’anga" - -pesoConvertible :: Currency -pesoConvertible = - Currency CUC 931 2 "Peso Convertible" - -pesoUruguayo :: Currency -pesoUruguayo = - Currency UYU 858 2 "Peso Uruguayo" - -philippinePeso :: Currency -philippinePeso = - Currency PHP 608 2 "Philippine Peso" - -platinum :: Currency -platinum = - Currency XPT 962 0 "Platinum" - -poundSterling :: Currency -poundSterling = - Currency GBP 826 2 "Pound Sterling" - -pula :: Currency -pula = - Currency BWP 072 2 "Pula" - -qatariRial :: Currency -qatariRial = - Currency QAR 634 2 "Qatari Rial" - -quetzal :: Currency -quetzal = - Currency GTQ 320 2 "Quetzal" - -rand :: Currency -rand = - Currency ZAR 710 2 "Rand" - -rialOmani :: Currency -rialOmani = - Currency OMR 512 3 "Rial Omani" - -riel :: Currency -riel = - Currency KHR 116 2 "Riel" - -romanianLeu :: Currency -romanianLeu = - Currency RON 946 2 "Romanian Leu" - -rufiyaa :: Currency -rufiyaa = - Currency MVR 462 2 "Rufiyaa" - -rupiah :: Currency -rupiah = - Currency IDR 360 2 "Rupiah" - -russianRuble :: Currency -russianRuble = - Currency RUB 643 2 "Russian Ruble" - -rwandaFranc :: Currency -rwandaFranc = - Currency RWF 646 0 "Rwanda Franc" - -sdr :: Currency -sdr = - Currency XDR 960 0 "SDR (Special Drawing Right)" - -saintHelenaPound :: Currency -saintHelenaPound = - Currency SHP 654 2 "Saint-Helena Pound" - -saudiRiyal :: Currency -saudiRiyal = - Currency SAR 682 2 "Saudi Riyal" - -serbianDinar :: Currency -serbianDinar = - Currency RSD 941 2 "Serbian Dinar" - -seychellesRupee :: Currency -seychellesRupee = - Currency SCR 690 2 "Seychelles Rupee" - -silver :: Currency -silver = - Currency XAG 961 0 "Silver" - -singaporeDollar :: Currency -singaporeDollar = - Currency SGD 702 2 "Singapore Dollar" - -sol :: Currency -sol = - Currency PEN 604 2 "Sol" - -solomonIslandsDollar :: Currency -solomonIslandsDollar = - Currency SBD 090 2 "Solomon Islands Dollar" - -som :: Currency -som = - Currency KGS 417 2 "Som" - -somaliShilling :: Currency -somaliShilling = - Currency SOS 706 2 "Somali Shilling" - -somoni :: Currency -somoni = - Currency TJS 972 2 "Somoni" - -southSudanesePound :: Currency -southSudanesePound = - Currency SSP 728 2 "South Sudanese Pound" - -sriLankaRupee :: Currency -sriLankaRupee = - Currency LKR 144 2 "Sri Lanka Rupee" - -sucre :: Currency -sucre = - Currency XSU 994 0 "Sucre" - -sudanesePound :: Currency -sudanesePound = - Currency SDG 938 2 "Sudanese Pound" - -surinamDollar :: Currency -surinamDollar = - Currency SRD 968 2 "Surinam Dollar" - -swedishKrona :: Currency -swedishKrona = - Currency SEK 752 2 "Swedish Krona" - -swissFranc :: Currency -swissFranc = - Currency CHF 756 2 "Swiss Franc" - -syrianPound :: Currency -syrianPound = - Currency SYP 760 2 "Syrian Pound" - -taka :: Currency -taka = - Currency BDT 050 2 "Taka" - -tala :: Currency -tala = - Currency WST 882 2 "Tala" - -tanzanianShilling :: Currency -tanzanianShilling = - Currency TZS 834 2 "Tanzanian Shilling" - -tenge :: Currency -tenge = - Currency KZT 398 2 "Tenge" - -noCurrency :: Currency -noCurrency = - Currency XXX 999 0 "The codes assigned for transactions where no currency is involved" - -trinidadAndTobagoDollar :: Currency -trinidadAndTobagoDollar = - Currency TTD 780 2 "Trinidad and Tobago Dollar" - -tugrik :: Currency -tugrik = - Currency MNT 496 2 "Tugrik" - -tunisianDinar :: Currency -tunisianDinar = - Currency TND 788 3 "Tunisian Dinar" - -turkishLira :: Currency -turkishLira = - Currency TRY 949 2 "Turkish Lira" - -turkmenistanNewManat :: Currency -turkmenistanNewManat = - Currency TMT 934 2 "Turkmenistan New Manat" - -uAEDirham :: Currency -uAEDirham = - Currency AED 784 2 "UAE Dirham" - -usDollar :: Currency -usDollar = - Currency USD 840 2 "US Dollar" - -usDollarNextday :: Currency -usDollarNextday = - Currency USN 997 2 "US Dollar (Next day)" - -ugandaShilling :: Currency -ugandaShilling = - Currency UGX 800 0 "Uganda" - -unidaddeFomento :: Currency -unidaddeFomento = - Currency CLF 990 4 "Unidad de Fomento" - -unidaddeValorReal :: Currency -unidaddeValorReal = - Currency COU 970 2 "Unidad de Valor Real" - -uruguayPesoEnUnidadesIndexadas :: Currency -uruguayPesoEnUnidadesIndexadas = - Currency UYI 940 0 "Uruguay Peso en Unidades Indexadas (URUIURUI)" - -uzbekistanSum :: Currency -uzbekistanSum = - Currency UZS 860 2 "Uzbekistan" - -vatu :: Currency -vatu = - Currency VUV 548 0 "Vatu" - -wirEuro :: Currency -wirEuro = - Currency CHE 947 2 "WIR Euro" - -wirFranc :: Currency -wirFranc = - Currency CHW 948 2 "WIR Franc" - -won :: Currency -won = - Currency KRW 410 0 "Won" - -yemeniRial :: Currency -yemeniRial = - Currency YER 886 2 "Yemeni Rial" - -yen :: Currency -yen = - Currency JPY 392 0 "Yen" - -yuanRenminbi :: Currency -yuanRenminbi = - Currency CNY 156 2 "Yuan Renminbi" - -zambianKwacha :: Currency -zambianKwacha = - Currency ZMW 967 2 "Zambian Kwacha" +instance Random Alpha where + random g = + let + (r, g') = + randomR (fromEnum (minBound :: Alpha), fromEnum(maxBound :: Alpha)) g + in + (toEnum r, g') -zimbabweDollar :: Currency -zimbabweDollar = - Currency ZWL 932 2 "Zimbabwe Dollar" + randomR (l, h) g = + let + (r, g') = + randomR (fromEnum l, fromEnum h) g + in + (toEnum r, g') + + +-- Create utilities + +-- | Obtain a Currency from its Alpha code +fromAlpha :: Alpha -> Currency +fromAlpha α = + case α of + AED -> Currency AED 784 2 "UAE Dirham" + AFN -> Currency AFN 971 2 "Afghani" + ALL -> Currency ALL 008 2 "Lek" + AMD -> Currency AMD 051 2 "Armenian Dram" + ANG -> Currency ANG 532 2 "Netherlands Antillean Guilder" + AOA -> Currency AOA 973 2 "Kwanza" + ARS -> Currency ARS 032 2 "Argentine Peso" + AUD -> Currency AUD 036 2 "Australian Dollar" + AWG -> Currency AWG 533 2 "Aruban Florin" + AZN -> Currency AZN 944 2 "Azerbaijan Manat" + BAM -> Currency BAM 977 2 "Convertible Mark" + BBD -> Currency BBD 052 2 "Barbados Dollar" + BDT -> Currency BDT 050 2 "Taka" + BGN -> Currency BGN 975 2 "Bulgarian Lev" + BHD -> Currency BHD 048 3 "Bahraini Dinar" + BIF -> Currency BIF 108 0 "Burundi Franc" + BMD -> Currency BMD 060 2 "Bermudian Dollar" + BND -> Currency BND 096 2 "Brunei Dollar" + BOB -> Currency BOB 068 2 "Boliviano" + BOV -> Currency BOV 984 2 "Mvdol" + BRL -> Currency BRL 986 2 "Brazilian Real" + BSD -> Currency BSD 044 2 "Bahamian Dollar" + BTN -> Currency BTN 064 2 "Ngultrum" + BWP -> Currency BWP 072 2 "Pula" + BYN -> Currency BYN 933 2 "Belarusian Ruble" + BZD -> Currency BZD 084 2 "Belize Dollar" + CAD -> Currency CAD 124 2 "Canadian Dollar" + CDF -> Currency CDF 976 2 "Congolese Franc" + CHE -> Currency CHE 947 2 "WIR Euro" + CHF -> Currency CHF 756 2 "Swiss Franc" + CHW -> Currency CHW 948 2 "WIR Franc" + CLF -> Currency CLF 990 4 "Unidad de Fomento" + CLP -> Currency CLP 152 0 "Chilean Peso" + CNY -> Currency CNY 156 2 "Yuan Renminbi" + COP -> Currency COP 170 2 "Colombian Peso" + COU -> Currency COU 970 2 "Unidad de Valor Real" + CRC -> Currency CRC 188 2 "Costa Rican Colon" + CUC -> Currency CUC 931 2 "Peso Convertible" + CUP -> Currency CUP 192 2 "Cuban Peso" + CVE -> Currency CVE 132 2 "Cabo Verde Escudo" + CZK -> Currency CZK 203 2 "Czech Koruna" + DJF -> Currency DJF 262 0 "Djibouti Franc" + DKK -> Currency DKK 208 2 "Danish Krone" + DOP -> Currency DOP 214 2 "Dominican Peso" + DZD -> Currency DZD 012 2 "Algerian Dinar" + EGP -> Currency EGP 818 2 "Egyptian Pound" + ERN -> Currency ERN 232 2 "Nakfa" + ETB -> Currency ETB 230 2 "Ethiopian Birr" + EUR -> Currency EUR 978 2 "Euro" + FJD -> Currency FJD 242 2 "Fiji Dollar" + FKP -> Currency FKP 238 2 "Falkland Islands Pound" + GBP -> Currency GBP 826 2 "Pound Sterling" + GEL -> Currency GEL 981 2 "Lari" + GHS -> Currency GHS 936 2 "Ghana Cedi" + GIP -> Currency GIP 292 2 "Gibraltar Pound" + GMD -> Currency GMD 270 2 "Dalasi" + GNF -> Currency GNF 324 0 "Guinean Franc" + GTQ -> Currency GTQ 320 2 "Quetzal" + GYD -> Currency GYD 328 2 "Guyana Dollar" + HKD -> Currency HKD 344 2 "Hong Kong Dollar" + HNL -> Currency HNL 340 2 "Lempira" + HRK -> Currency HRK 191 2 "Kuna" + HTG -> Currency HTG 332 2 "Gourde" + HUF -> Currency HUF 348 2 "Forint" + IDR -> Currency IDR 360 2 "Rupiah" + ILS -> Currency ILS 376 2 "New Israeli Sheqel" + INR -> Currency INR 356 2 "Indian Rupee" + IQD -> Currency IQD 368 3 "Iraqi Dinar" + IRR -> Currency IRR 364 2 "Iranian Rial" + ISK -> Currency ISK 352 0 "Iceland Krona" + JMD -> Currency JMD 388 2 "Jamaican Dollar" + JOD -> Currency JOD 400 3 "Jordanian Dinar" + JPY -> Currency JPY 392 0 "Yen" + KES -> Currency KES 404 2 "Kenyan Shilling" + KGS -> Currency KGS 417 2 "Som" + KHR -> Currency KHR 116 2 "Riel" + KMF -> Currency KMF 174 0 "Comorian Franc" + KPW -> Currency KPW 408 2 "North Korean Won" + KRW -> Currency KRW 410 0 "Won" + KWD -> Currency KWD 414 3 "Kuwaiti Dinar" + KYD -> Currency KYD 136 2 "Cayman Islands Dollar" + KZT -> Currency KZT 398 2 "Tenge" + LAK -> Currency LAK 418 2 "Lao Kip" + LBP -> Currency LBP 422 2 "Lebanese Pound" + LKR -> Currency LKR 144 2 "Sri Lanka Rupee" + LRD -> Currency LRD 430 2 "Liberian Dollar" + LSL -> Currency LSL 426 2 "Loti" + LYD -> Currency LYD 434 3 "Libyan Dinar" + MAD -> Currency MAD 504 2 "Moroccan Dirham" + MDL -> Currency MDL 498 2 "Moldovan Leu" + MGA -> Currency MGA 969 2 "Malagasy Ariary" + MKD -> Currency MKD 807 2 "Denar" + MMK -> Currency MMK 104 2 "Kyat" + MNT -> Currency MNT 496 2 "Tugrik" + MOP -> Currency MOP 446 2 "Pataca" + MRO -> Currency MRO 478 2 "Ouguiya" + MUR -> Currency MUR 480 2 "Mauritius Rupee" + MVR -> Currency MVR 462 2 "Rufiyaa" + MWK -> Currency MWK 454 2 "Malawi Kwacha" + MXN -> Currency MXN 484 2 "Mexican Peso" + MXV -> Currency MXV 979 2 "Mexican Unidad de Inversion (UDI)" + MYR -> Currency MYR 458 2 "Malaysian Ringgit" + MZN -> Currency MZN 943 2 "Mozambique Metical" + NAD -> Currency NAD 516 2 "Namibia Dollar" + NGN -> Currency NGN 566 2 "Naira" + NIO -> Currency NIO 558 2 "Cordoba Oro" + NOK -> Currency NOK 578 2 "Norwegian Krone" + NPR -> Currency NPR 524 2 "Nepalese Rupee" + NZD -> Currency NZD 554 2 "New Zealand Dollar" + OMR -> Currency OMR 512 3 "Rial Omani" + PAB -> Currency PAB 590 2 "Balboa" + PEN -> Currency PEN 604 2 "Sol" + PGK -> Currency PGK 598 2 "Kina" + PHP -> Currency PHP 608 2 "Philippine Peso" + PKR -> Currency PKR 586 2 "Pakistan Rupee" + PLN -> Currency PLN 985 2 "Zloty" + PYG -> Currency PYG 600 0 "Guarani" + QAR -> Currency QAR 634 2 "Qatari Rial" + RON -> Currency RON 946 2 "Romanian Leu" + RSD -> Currency RSD 941 2 "Serbian Dinar" + RUB -> Currency RUB 643 2 "Russian Ruble" + RWF -> Currency RWF 646 0 "Rwanda Franc" + SAR -> Currency SAR 682 2 "Saudi Riyal" + SBD -> Currency SBD 090 2 "Solomon Islands Dollar" + SCR -> Currency SCR 690 2 "Seychelles Rupee" + SDG -> Currency SDG 938 2 "Sudanese Pound" + SEK -> Currency SEK 752 2 "Swedish Krona" + SGD -> Currency SGD 702 2 "Singapore Dollar" + SHP -> Currency SHP 654 2 "Saint-Helena Pound" + SLL -> Currency SLL 694 2 "Leone" + SOS -> Currency SOS 706 2 "Somali Shilling" + SRD -> Currency SRD 968 2 "Surinam Dollar" + SSP -> Currency SSP 728 2 "South Sudanese Pound" + STD -> Currency STD 678 2 "Dobra" + SVC -> Currency SVC 222 2 "El Salvador Colon" + SYP -> Currency SYP 760 2 "Syrian Pound" + SZL -> Currency SZL 748 2 "Lilangeni" + THB -> Currency THB 764 2 "Baht" + TJS -> Currency TJS 972 2 "Somoni" + TMT -> Currency TMT 934 2 "Turkmenistan New Manat" + TND -> Currency TND 788 3 "Tunisian Dinar" + TOP -> Currency TOP 776 2 "Pa’anga" + TRY -> Currency TRY 949 2 "Turkish Lira" + TTD -> Currency TTD 780 2 "Trinidad and Tobago Dollar" + TWD -> Currency TWD 901 2 "New Taiwan Dollar" + TZS -> Currency TZS 834 2 "Tanzanian Shilling" + UAH -> Currency UAH 980 2 "Hryvnia" + UGX -> Currency UGX 800 0 "Uganda" + USD -> Currency USD 840 2 "US Dollar" + USN -> Currency USN 997 2 "US Dollar (Next day)" + UYI -> Currency UYI 940 0 "Uruguay Peso en Unidades Indexadas (URUIURUI)" + UYU -> Currency UYU 858 2 "Peso Uruguayo" + UZS -> Currency UZS 860 2 "Uzbekistan" + VEF -> Currency VEF 937 2 "Bolívar" + VND -> Currency VND 704 0 "Dong" + VUV -> Currency VUV 548 0 "Vatu" + WST -> Currency WST 882 2 "Tala" + XAF -> Currency XAF 950 0 "CFA Franc BEAC" + XAG -> Currency XAG 961 0 "Silver" + XAU -> Currency XAU 959 0 "Gold" + XBA -> Currency XBA 955 0 "Bond Markets Unit European Composite Unit (EURCO)" + XBB -> Currency XBB 956 0 "Bond Markets Unit European Monetary Unit (E.M.U.-6)" + XBC -> Currency XBC 957 0 "Bond Markets Unit European Unit of Account 9 (E.U.A.-9)" + XBD -> Currency XBD 958 0 "Bond Markets Unit European Unit of Account 17 (E.U.A.-17)" + XCD -> Currency XCD 951 2 "East Caribbean Dollar" + XDR -> Currency XDR 960 0 "SDR (Special Drawing Right)" + XOF -> Currency XOF 952 0 "CFA Franc BCEAO" + XPD -> Currency XPD 964 0 "Palladium" + XPF -> Currency XPF 953 0 "CFP Franc" + XPT -> Currency XPT 962 0 "Platinum" + XSU -> Currency XSU 994 0 "Sucre" + XTS -> Currency XTS 963 0 "Codes specifically reserved for testing purposes" + XUA -> Currency XUA 965 0 "ADB Unit of Account" + XXX -> Currency XXX 999 0 "The codes assigned for transactions where no currency is involved" + YER -> Currency YER 886 2 "Yemeni Rial" + ZAR -> Currency ZAR 710 2 "Rand" + ZMW -> Currency ZMW 967 2 "Zambian Kwacha" + ZWL -> Currency ZWL 932 2 "Zimbabwe Dollar" -zloty :: Currency -zloty = - Currency PLN 985 2 "Zloty" -- | List of all currencies in the standard currencies :: [Currency] currencies = - [ unitOfAccount - , afghani - , algerianDinar - , argentinePeso - , armenianDram - , arubanFlorin - , australianDollar - , azerbaijanManat - , bahamianDollar - , bahrainiDinar - , baht - , balboa - , barbadosDollar - , belarusianRuble - , belizeDollar - , bermudianDollar - , boliviano - , bolívar - , bondMarketsCompositeUnit - , bondMarketsMonetaryUnit - , bondMarketsUnitofAccount17 - , bondMarketsUnitofAccount9 - , brazilianReal - , bruneiDollar - , bulgarianLev - , burundiFranc - , cfaFrancBCEAO - , cfaFrancBEAC - , cfpFranc - , caboVerdeEscudo - , canadianDollar - , caymanIslandsDollar - , chileanPeso - , testing - , colombianPeso - , comorianFranc - , congoleseFranc - , convertibleMark - , cordobaOro - , costaRicanColon - , cubanPeso - , czechKoruna - , dalasi - , danishKrone - , denar - , djiboutiFranc - , dobra - , dominicanPeso - , dong - , eastCaribbeanDollar - , egyptianPound - , elSalvadorColon - , ethiopianBirr - , euro - , falklandIslandsPound - , fijiDollar - , forint - , ghanaCedi - , gibraltarPound - , gold - , gourde - , guarani - , guineanFranc - , guyanaDollar - , hongKongDollar - , hryvnia - , icelandKrona - , indianRupee - , iranianRial - , iraqiDinar - , jamaicanDollar - , jordanianDinar - , kenyanShilling - , kina - , kuna - , kuwaitiDinar - , kwanza - , kyat - , laoKip - , lari - , lebanesePound - , lek - , lempira - , leone - , liberianDollar - , libyanDinar - , lilangeni - , loti - , malagasyAriary - , malawiKwacha - , malaysianRinggit - , mauritiusRupee - , mexicanPeso - , mexicanUnidadDeInversion - , moldovanLeu - , moroccanDirham - , mozambiqueMetical - , mvdol - , naira - , nakfa - , namibiaDollar - , nepaleseRupee - , netherlandsAntilleanGuilder - , newIsraeliSheqel - , newTaiwanDollar - , newZealandDollar - , ngultrum - , northKoreanWon - , norwegianKrone - , ouguiya - , pakistanRupee - , palladium - , pataca - , paanga - , pesoConvertible - , pesoUruguayo - , philippinePeso - , platinum - , poundSterling - , pula - , qatariRial - , quetzal - , rand - , rialOmani - , riel - , romanianLeu - , rufiyaa - , rupiah - , russianRuble - , rwandaFranc - , sdr - , saintHelenaPound - , saudiRiyal - , serbianDinar - , seychellesRupee - , silver - , singaporeDollar - , sol - , solomonIslandsDollar - , som - , somaliShilling - , somoni - , southSudanesePound - , sriLankaRupee - , sucre - , sudanesePound - , surinamDollar - , swedishKrona - , swissFranc - , syrianPound - , taka - , tala - , tanzanianShilling - , tenge - , noCurrency - , trinidadAndTobagoDollar - , tugrik - , tunisianDinar - , turkishLira - , turkmenistanNewManat - , uAEDirham - , usDollar - , usDollarNextday - , ugandaShilling - , unidaddeFomento - , unidaddeValorReal - , uruguayPesoEnUnidadesIndexadas - , uzbekistanSum - , vatu - , wirEuro - , wirFranc - , won - , yemeniRial - , yen - , yuanRenminbi - , zambianKwacha - , zloty - , zimbabweDollar - ] + fmap fromAlpha [minBound..maxBound] + + +-- | List of all alpha constructors as strings +alphas :: [String] +alphas = + fmap show $ dataTypeConstrs $ dataTypeOf (minBound :: Alpha) diff --git a/test/Data/CurrencySpec.hs b/test/Data/CurrencySpec.hs new file mode 100644 index 0000000..752b9e4 --- /dev/null +++ b/test/Data/CurrencySpec.hs @@ -0,0 +1,54 @@ +-- | Specifications for the Data.Currency module +{-# OPTIONS_GHC -fno-warn-orphans #-} + +module Data.CurrencySpec + ( spec + ) where + +import Data.Bson (Val (..)) +import Test.Hspec (Spec, describe, it) +import Test.QuickCheck (Arbitrary (..), property) +import Test.QuickCheck.Gen (chooseAny) + +import qualified Data.Aeson as Aeson + +import Data.Currency (Alpha, Currency (..), fromAlpha) + + +instance Arbitrary Currency where + arbitrary = + chooseAny + + +instance Arbitrary Alpha where + arbitrary = + chooseAny + + +spec :: Spec +spec = do + describe "Round-up properties (Currency)" $ do + it "Read . Show = id" $ property $ + \x -> (read . show) x == (x :: Currency) + + it "FromJSON . ToJSON = pure" $ property $ + \x -> (Aeson.eitherDecode . Aeson.encode) x == pure (x :: Currency) + + it "cast' . val === pure" $ property $ + \x -> (cast' . val) x == pure (x :: Currency) + + + describe "Round-up properties (Alpha)" $ do + it "Read . Show = id" $ property $ + \x -> (read . show) x == (x :: Alpha) + + it "FromJSON . ToJSON = pure" $ property $ + \x -> (Aeson.eitherDecode . Aeson.encode) x == pure (x :: Alpha) + + it "cast' . val === pure" $ property $ + \x -> (cast' . val) x == pure (x :: Alpha) + + + describe "fromAlpha" $ + it "alpha . fromAlpha = id" $ property $ + \x -> (alpha . fromAlpha) x == x diff --git a/test/Spec.hs b/test/Spec.hs new file mode 100644 index 0000000..a824f8c --- /dev/null +++ b/test/Spec.hs @@ -0,0 +1 @@ +{-# OPTIONS_GHC -F -pgmF hspec-discover #-}