diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Daniel Campoverde [alx741] (c) 2017
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Daniel Campoverde [alx741] nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+[![CircleCI](https://circleci.com/gh/alx741/currencies.svg?style=svg)](https://circleci.com/gh/alx741/currencies)
+
+# currencies
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/currencies.cabal b/currencies.cabal
new file mode 100644
--- /dev/null
+++ b/currencies.cabal
@@ -0,0 +1,45 @@
+name:                currencies
+version:             0.1.0.0
+synopsis:            Currencies representation, pretty printing and conversion
+description:         ISO 4217 Currencies representation, pretty printing and conversion:
+    .
+    * Represent monetary amouts of a particular currency in a type-safe manner
+    .
+    * Convert amounts between different currencies
+    .
+    * Print human readable amouts
+homepage:            https://github.com/alx741/currencies#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Daniel Campoverde [alx741]
+maintainer:          alx@sillybytes.net
+copyright:           2017 Daniel Campoverde [alx741]
+category:            Data
+build-type:          Simple
+extra-source-files:  README.md
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Data.Currency.Currencies
+                     , Data.Currency.Amounts
+                     , Data.Currency.Pretty
+  build-depends:       base >= 4.7 && < 5
+                     , text >= 1.2 && < 2
+  default-language:    Haskell2010
+
+test-suite currencies-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  other-modules:       Data.Currency.PrettySpec
+  build-depends:       base
+                     , currencies
+                     , hspec >= 2.0 && < 3
+                     , text >= 1.2 && < 2
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/alx741/currencies
diff --git a/src/Data/Currency/Amounts.hs b/src/Data/Currency/Amounts.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Currency/Amounts.hs
@@ -0,0 +1,53 @@
+-- | Operations upon monetary 'Amount's
+--
+-- Converting amounts
+--
+-- >>> convert USD (Amount EUR 23482.34)
+-- Amount USD 27709.1612
+--
+-- >>>  prettyPrint $ convert USD (Amount EUR 23482.34)
+-- "USD 27,709.16"
+--
+-- Comparing amounts
+--
+-- >>> compareAmounts  (Amount EUR 1000) (Amount BTC 1)
+-- LT
+
+module Data.Currency.Amounts
+    ( -- * Monetary Amount
+      Amount(..)
+
+      -- * Converting
+    , toUSD
+    , fromUSD
+    , convert
+
+      -- * Comparing
+    , compareAmounts
+
+    , module Data.Currency.Currencies
+    ) where
+
+import Data.Currency.Currencies
+
+-- | Monetary amounts
+data Amount c = Amount c Double deriving (Show, Read, Eq)
+
+instance (Currency c) => Ord (Amount c) where
+    (Amount _ v1) <= (Amount _ v2) = v1 <= v2
+
+-- | Convert an 'Amount' of an arbitrary currency to 'USD'
+toUSD :: (Currency c) => Amount c -> Amount USD
+toUSD (Amount c amount) = Amount USD $ amount * exchangeUSD c
+
+-- | Convert an 'Amount' from 'USD' to a given 'Currency'
+fromUSD :: (Currency c) => c -> Amount USD -> Amount c
+fromUSD c (Amount USD amount) = Amount c $ amount / exchangeUSD c
+
+-- | Convert an 'Amount' to a given 'Currency'
+convert :: (Currency c', Currency c) => c' -> Amount c -> Amount c'
+convert c' amount = fromUSD c' $ toUSD amount
+
+-- | Compare two 'Amount's of arbitrary currencies
+compareAmounts :: (Currency c1, Currency c2) => Amount c1 -> Amount c2 -> Ordering
+compareAmounts a1 a2 = compare (toUSD a1) (toUSD a2)
diff --git a/src/Data/Currency/Currencies.hs b/src/Data/Currency/Currencies.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Currency/Currencies.hs
@@ -0,0 +1,89 @@
+-- | ISO 4217 compliant and other currencies
+
+module Data.Currency.Currencies
+    ( -- * Currency Class
+      Currency(..)
+    , CurrencyType(..)
+
+      -- * Currencies
+    , BTC(..)
+    , CLP(..)
+    , EUR(..)
+    , USD(..)
+    ) where
+
+class (Show c, Eq c) => Currency c where
+    currencyType :: c -> CurrencyType
+    -- | ISO 4217 Currency Code
+    isoCode :: c -> String
+    -- | ISO 4217 Currency Numeric Code
+    isoNumericCode :: c -> String
+    -- | Number of digits after the decimal separator
+    decimalDigits :: c -> Int
+    -- | Currency UTF-8 symbol
+    symbol :: c -> String
+    -- | Exchange rate with US Dollar (USD)
+    exchangeUSD :: c -> Double
+    -- | ISO 3166-1 alpha-2 Country codes where the currency is used
+    countries :: c -> [String]
+
+data CurrencyType
+  = Circulating -- ^ Currencies recognized as legal tender
+  | Local -- ^ Currencies with validity only in particular geographical localities
+  | Supranational -- ^ Currencies for procedural purposes and precious metals (X currencies)
+  | Cryptocurrency -- ^ Digital, cryptography based currencies
+  | Fictional -- ^ Currencies used in games, movies, novels, and other fictional setups
+  deriving (Show, Read, Eq)
+
+
+-- | Bitcoin
+data BTC = BTC deriving (Show, Read, Eq)
+
+-- | Chilean Peso
+data CLP = CLP deriving (Show, Read, Eq)
+
+-- | European Union Euro
+data EUR = EUR deriving (Show, Read, Eq)
+
+-- | US Dollar
+data USD = USD deriving (Show, Read, Eq)
+
+
+instance Currency BTC where
+    currencyType _ = Cryptocurrency
+    isoCode = show
+    isoNumericCode _ = ""
+    decimalDigits _ = 8
+    symbol _ = "B"
+    exchangeUSD _ = 4237.88
+    countries _ = []
+
+instance Currency CLP where
+    currencyType _ = Circulating
+    isoCode = show
+    isoNumericCode _ = "152"
+    decimalDigits _ = 0
+    symbol _ = "$"
+    exchangeUSD _ = 0.0015
+    countries _ = ["CL"]
+
+instance Currency EUR where
+    currencyType _ = Circulating
+    isoCode = show
+    isoNumericCode _ = "978"
+    decimalDigits _ = 2
+    symbol _ = "€"
+    exchangeUSD _ = 1.18
+    countries _ = ["AD", "AT", "BE", "CY", "EE", "FI", "FR", "DE", "GR"
+        , "GP", "IE", "IT", "LV", "LT", "LU", "MT", "MQ", "YT", "MC"
+        , "ME", "NL", "PT", "RE", "BL", "PM", "SM", "SK", "SI", "ES"]
+
+instance Currency USD where
+    currencyType _ = Circulating
+    isoCode = show
+    isoNumericCode _ = "840"
+    decimalDigits _ = 2
+    symbol _ = "$"
+    exchangeUSD _ = 1.0
+    countries _ = ["US", "AS", "BB", "BM", "IO", "VG", "BQ", "EC", "MH"
+        , "FM", "MP", "PW", "PA", "PR", "TL", "TC", "VI"]
diff --git a/src/Data/Currency/Pretty.hs b/src/Data/Currency/Pretty.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Currency/Pretty.hs
@@ -0,0 +1,132 @@
+-- | Pretty print monetary amounts like:
+--
+-- * /$ 34.50/
+--
+-- * /USD 3,456.29/
+--
+-- * /€ 32 433 938.23/
+--
+-- Using default printing settings
+--
+-- >>> prettyPrint (Amount USD 2342.2)
+-- "USD 2,342.20"
+-- >>> prettyPrint (Amount EUR 45827.346)
+-- "EUR 45,827.35"
+--
+-- Using custom printing settings
+--
+-- >>> prettyPrintWith (defaultConfig { useCurrencySymbol = True }) (Amount USD 2342.2)
+-- "$ 2,342.20"
+-- >>> prettyPrintWith (defaultConfig { useCurrencySymbol = True }) (Amount EUR 2342.2)
+-- "€ 2,342.20"
+-- >>> prettyPrintWith (defaultConfig { showDecimals = False }) (Amount USD 25.50)
+-- "USD 25"
+--
+-- For more printing settings see 'PrettyConfig'
+
+module Data.Currency.Pretty
+    ( -- * Pretty printing
+      prettyPrint
+    , prettyPrintWith
+
+      -- * Configuration
+    , PrettyConfig(..)
+    , defaultConfig
+
+    , module Data.Currency.Amounts
+    ) where
+
+import Text.Printf
+import Data.Currency.Amounts
+import Data.Monoid ((<>))
+
+-- | Pretty print a monetary amount using 'defaultConfig'
+prettyPrint :: (Currency c) => Amount c -> String
+prettyPrint = prettyPrintWith defaultConfig
+
+-- | Pretty print a monetary amount with a custom 'PrettyConfig' configuration
+prettyPrintWith :: (Currency c) => PrettyConfig -> Amount c -> String
+prettyPrintWith cnf (Amount currency amount) =
+    prefixSymbol currency cnf
+    $ prefixCode currency cnf
+    $ changeDecimalSep currency cnf
+    $ largeAmountSeparate currency cnf
+    $ toDecimalString currency cnf amount
+
+prefixSymbol :: (Currency c) => c -> PrettyConfig -> String -> String
+prefixSymbol currency cnf val
+    | useCurrencySymbol cnf = symbol currency <> " " <> val
+    | otherwise = val
+
+prefixCode :: (Currency c) => c -> PrettyConfig -> String -> String
+prefixCode currency cnf val
+    | useCurrencySymbol cnf = val
+    | suffixIsoCode cnf = val <> " " <> isoCode currency
+    | otherwise = isoCode currency <> " " <> val
+
+changeDecimalSep :: (Currency c) => c -> PrettyConfig -> String -> String
+changeDecimalSep currency cnf = replaceFst '.' (decimalSeparator cnf)
+    where
+        replaceFst :: Char -> Char -> String -> String
+        replaceFst c c' [] = []
+        replaceFst c c' (s:ss)
+            | s == c = c' : ss
+            | otherwise = s : replaceFst c c' ss
+
+largeAmountSeparate :: (Currency c) => c -> PrettyConfig -> String -> String
+largeAmountSeparate currency cnf amount
+    | compactFourDigitAmounts cnf = if length integer <= 4 then amount else separated ++ decimal
+    | otherwise = separated ++ decimal
+    where
+        (integer, decimal) = span (/= '.') amount
+        separated = reverse $ intersperseN 3 (largeAmountSeparator cnf) $ reverse integer
+
+toDecimalString :: (Currency c) => c -> PrettyConfig -> Double -> String
+toDecimalString currency cnf amount
+    | showDecimals cnf = printf format amount
+    | otherwise = takeWhile (/= '.') $ printf "%.1f" amount
+    where format = "%." <> show (decimalDigits currency) <> "f"
+
+intersperseN :: Eq a => Int -> a -> [a] -> [a]
+intersperseN n s ss
+    | null remainder = ss
+    | otherwise = (take ++ [s]) ++ intersperseN n s remainder
+    where (take, remainder) = splitAt n ss
+
+
+data PrettyConfig = PrettyConfig
+    { showDecimals :: Bool
+    -- | Print four digits amounts as
+    -- /USD 1000,00/ instead of /USD 1,000.00/
+    , compactFourDigitAmounts :: Bool
+    -- | Replace the currency ISO code with its symbol to produce
+    -- /$ 23.50/ instead of /USD 23.50/
+    , useCurrencySymbol :: Bool
+    -- | Use the currency ISO code as suffix to produce
+    -- /23.50 USD/ instead of /USD 23.50/
+    , suffixIsoCode :: Bool
+    , largeAmountSeparator :: Char
+    , decimalSeparator :: Char
+    } deriving (Show)
+
+
+-- | Default 'PrettyConfig' used in 'prettyPrint'
+--
+-- * Show decimals
+--
+-- * Compact four digit amounts
+--
+-- * Use ISO code
+--
+-- * Separate large amounts with comma
+--
+-- * Separate decimals with dot
+defaultConfig :: PrettyConfig
+defaultConfig = PrettyConfig
+    { showDecimals = True
+    , compactFourDigitAmounts = True
+    , useCurrencySymbol = False
+    , suffixIsoCode = False
+    , largeAmountSeparator = ','
+    , decimalSeparator = '.'
+    }
diff --git a/test/Data/Currency/PrettySpec.hs b/test/Data/Currency/PrettySpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Data/Currency/PrettySpec.hs
@@ -0,0 +1,62 @@
+module Data.Currency.PrettySpec where
+
+import Test.Hspec
+import Data.Currency.Pretty
+import Data.Currency.Amounts
+
+spec :: Spec
+spec = do
+    describe "prettyPrint" $ do
+        it "prints human readable monetary amounts" $ do
+            prettyPrint (Amount USD 23.50)  `shouldBe` "USD 23.50"
+            prettyPrint (Amount USD 540.256)  `shouldBe` "USD 540.26"
+            prettyPrint (Amount USD 300.251)  `shouldBe` "USD 300.25"
+            prettyPrint (Amount USD 3.4)  `shouldBe` "USD 3.40"
+            prettyPrint (Amount EUR 15.589)  `shouldBe` "EUR 15.59"
+
+        it "respects currency decimal digits" $ do
+            prettyPrint (Amount CLP 345.35)  `shouldBe` "CLP 345"
+            prettyPrint (Amount CLP 23.53)  `shouldBe` "CLP 24"
+
+        it "can use the currency code as suffix" $ do
+            let config = defaultConfig { suffixIsoCode = True }
+            prettyPrintWith config (Amount USD 23.50)  `shouldBe` "23.50 USD"
+            prettyPrintWith config (Amount CLP 345.35)  `shouldBe` "345 CLP"
+
+        it "can omit decimals" $ do
+            let config = defaultConfig { showDecimals = False }
+            prettyPrintWith config (Amount USD 23.50)  `shouldBe` "USD 23"
+            prettyPrintWith config (Amount USD 534.25)  `shouldBe` "USD 534"
+            prettyPrintWith config (Amount EUR 15.589)  `shouldBe` "EUR 15"
+
+        it "can use the currency symbol" $ do
+            let config = defaultConfig { useCurrencySymbol = True }
+            prettyPrintWith config (Amount USD 23.50)  `shouldBe` "$ 23.50"
+            prettyPrintWith config (Amount EUR 15.589)  `shouldBe` "€ 15.59"
+            prettyPrintWith config (Amount BTC 0.5898)  `shouldBe` "B 0.58980000"
+
+        it "can use a custom decimal separator" $ do
+            let config = defaultConfig { decimalSeparator = ',' }
+            prettyPrintWith config (Amount USD 23.50)  `shouldBe` "USD 23,50"
+            prettyPrintWith config (Amount EUR 15.589)  `shouldBe` "EUR 15,59"
+            prettyPrintWith config (Amount USD 23.0)  `shouldBe` "USD 23,00"
+
+        it "uses large amounts separators" $ do
+            prettyPrint (Amount USD 32323.50)  `shouldBe` "USD 32,323.50"
+            prettyPrint (Amount EUR 3827115.259)  `shouldBe` "EUR 3,827,115.26"
+
+        it "can use a custom large amounts separator" $ do
+            let config = defaultConfig { largeAmountSeparator = ' ' }
+            prettyPrintWith config (Amount USD 32323.50)  `shouldBe` "USD 32 323.50"
+            prettyPrintWith config (Amount EUR 3827115.259)  `shouldBe` "EUR 3 827 115.26"
+
+        it "can avoid separating 4 digit amounts" $ do
+            prettyPrint (Amount USD 2323.50)  `shouldBe` "USD 2323.50"
+            prettyPrint (Amount EUR 4629.25)  `shouldBe` "EUR 4629.25"
+            prettyPrint (Amount USD 23875.00)  `shouldBe` "USD 23,875.00"
+
+        it "can force 4-digit amounts separation" $ do
+            let config = defaultConfig { compactFourDigitAmounts = False}
+            prettyPrintWith config (Amount USD 2323.50)  `shouldBe` "USD 2,323.50"
+            prettyPrintWith config (Amount EUR 4629.25)  `shouldBe` "EUR 4,629.25"
+            prettyPrintWith config (Amount USD 23875.00)  `shouldBe` "USD 23,875.00"
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
