diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,12 @@
+# Version 0.9.1
+
+* Add approximation method `HalfAwayFromZero`, also known as “kaufmännisches Runden”
+  in German speaking countries. See issue #55.
+  
+* Fix compilation with GHC 9. See issue #59.
+
+* Added `exchangeRate'`. See issue #61.
+
 # Version 0.9
 
 * _BREAKING CHANGE, POSSIBLY REQUIRING HUMAN INTERVENTION_. Changed
diff --git a/safe-money.cabal b/safe-money.cabal
--- a/safe-money.cabal
+++ b/safe-money.cabal
@@ -1,5 +1,5 @@
 name: safe-money
-version: 0.9
+version: 0.9.1
 license: BSD3
 license-file: LICENSE
 copyright: Copyright (c) Renzo Carbonara 2016-2019
diff --git a/src/Money.hs b/src/Money.hs
--- a/src/Money.hs
+++ b/src/Money.hs
@@ -73,6 +73,7 @@
    -- * Currency exchange
  , I.ExchangeRate
  , I.exchangeRate
+ , I.exchangeRate'
  , I.exchange
  , I.exchangeRateRecip
  , I.exchangeRateFromDecimal
diff --git a/src/Money/Internal.hs b/src/Money/Internal.hs
--- a/src/Money/Internal.hs
+++ b/src/Money/Internal.hs
@@ -21,7 +21,7 @@
 {-# OPTIONS_GHC -Wno-redundant-constraints #-}
 
 -- | This is an internal module. You may use stuff exported from here, but we
--- can't garantee their stability.
+-- can't guarantee their stability.
 module Money.Internal
  ( -- * Dense monetary values
    Dense
@@ -53,6 +53,7 @@
    -- * Currency exchange
  , ExchangeRate
  , exchangeRate
+ , exchangeRate'
  , exchange
  , exchangeRateFromDecimal
  , exchangeRateToDecimal
@@ -96,7 +97,7 @@
  , rationalToDecimal
  , rationalFromDecimal
  -- * Miscellaneous
- , Approximation(Round, Floor, Ceiling, Truncate, HalfEven)
+ , Approximation(Round, Floor, Ceiling, Truncate, HalfEven, HalfAwayFromZero)
  , approximate
  -- ** Decimal config
  , DecimalConf(..)
@@ -163,7 +164,7 @@
 -- of @USD 3.41@ is @USD 1.705@, which is not an amount that can't be
 -- represented as a number of USD cents (the smallest unit that can
 -- represent USD amounts). Nevertheless, if you do manage to represent @USD
--- 1.709@ somehow, and you eventually multiply @USD 1.705@ by @4@ for
+-- 1.705@ somehow, and you eventually multiply @USD 1.705@ by @4@ for
 -- example, then you end up with @USD 6.82@, which is again a value
 -- representable as USD cents. In other words, 'Dense' monetary values
 -- allow us to perform precise calculations deferring the conversion to a
@@ -335,7 +336,7 @@
 -- 'discrete' 2105 :: 'Discrete' \"GBP\" \"penny\"
 -- @
 --
--- Because @2015 / 100 == 20.15@.
+-- Because @2105 / 100 == 21.05@.
 type Discrete (currency :: Symbol) (unit :: Symbol)
   = Discrete' currency (UnitScale currency unit)
 
@@ -479,7 +480,7 @@
   .  (KnownSymbol currency, GoodScale scale)
   => Discrete' currency scale
   -> String -- ^
-discreteCurrency' = \_ -> symbolVal (Proxy @ currency)
+discreteCurrency' = \_ -> symbolVal (Proxy @currency)
 {-# INLINE discreteCurrency' #-}
 
 -- | Method for approximating a fractional number to an integer number.
@@ -496,6 +497,10 @@
   | HalfEven
   -- ^ Approximate @x@ to the nearest even integer, when equidistant from the
   -- nearest two integers. This is also known as “Bankers Rounding”.
+  | HalfAwayFromZero
+  -- ^ Approximate @x@ to the nearest integer, or to the nearest integer away
+  -- from zero if @x@ is equidistant between to integers. This is known
+  -- as “kaufmännisches Runden” in German speaking countries.
   deriving (Eq, Ord, Show, Read, GHC.Generic)
 
 approximate :: Approximation -> Rational -> Integer
@@ -506,6 +511,7 @@
   Ceiling -> ceiling
   Truncate -> truncate
   HalfEven -> halfEven
+  HalfAwayFromZero -> halfAwayFromZero
 
 -- | Approximate to the nearest even integer, when equidistant from the nearest
 -- two integers. This is also known as “Bankers Rounding”.
@@ -518,7 +524,20 @@
         | even tr -> tr
         | otherwise -> tr + signum tr
 
+-- | Approximate @x@ to the nearest integer, or to the nearest integer away
+-- from zero if @x@ is equidistant between to integers. This is known
+-- as “kaufmännisches Runden” in German speaking countries.
 
+halfAwayFromZero :: Rational -> Integer
+{-# INLINABLE halfAwayFromZero #-}
+halfAwayFromZero = \r ->                   --    1.5    -1.5
+  let s   :: Integer  = truncate (signum r)
+      ar  :: Rational = abs r              --    1.5     1.5
+      tr  :: Integer  = truncate ar        --    1.0     1.0
+      rr  :: Rational = ar - toRational tr --    0.5     0.5
+  in if | rr < 1%2  -> s * tr
+        | otherwise -> s * (tr + 1)
+
 -- | Approximate a 'Dense' value @x@ to the nearest value fully representable a
 -- given @scale@.
 --
@@ -797,6 +816,34 @@
   else Nothing
 {-# INLINE exchangeRate #-}
 
+-- | Unsafely build an 'ExchageRate' monetary value from a 'Rational' value.
+-- Contrary to 'exchangeRate', this function *crashes* if the given 'Rational'
+-- a value has zero as a denominator or when it is negative, with the former
+-- case being something very unlikely to happen unless the given 'Rational'
+-- was itself unsafely constructed. Other than that, 'exchangeRate' and
+-- 'exchangeRate'' behave the same.
+--
+-- Prefer to use 'exchangeRate' when dealing with 'Rational' inputs from
+-- untrusted sources.
+--
+-- @
+-- 'denominator' x /= 0 && x > 0
+--   ⇒ 'exchangeRate' x == 'Just' ('exchangeRate'' x)
+-- @
+--
+-- @
+-- 'denominator' x == 0 || x <= 0
+--   ⇒ 'undefined' == 'exchangeRate'' x
+-- @
+exchangeRate' :: Rational -> ExchangeRate src dst
+exchangeRate' = \r ->
+  if denominator r /= 0 && r > 0
+  then ExchangeRate r
+  else if denominator r == 0
+       then error "exchangeRate': malformed Rational given (denominator is zero)."
+       else error "exchangeRate': malformed Rational given (is negative)."
+{-# INLINABLE exchangeRate' #-}
+
 -- | Reciprocal 'ExchangeRate'.
 --
 -- This function retuns the reciprocal or multiplicative inverse of the given
@@ -895,7 +942,7 @@
 -- | Convert a 'Dense' to a 'SomeDense' for ease of serialization.
 toSomeDense :: KnownSymbol currency => Dense currency -> SomeDense
 toSomeDense = \(Dense r0 :: Dense currency) ->
-  SomeDense (symbolVal (Proxy @ currency)) r0
+  SomeDense (symbolVal (Proxy @currency)) r0
 {-# INLINE toSomeDense #-}
 
 -- | Attempt to convert a 'SomeDense' to a 'Dense', provided you know the target
@@ -979,7 +1026,7 @@
 someDiscreteAmount = _someDiscreteAmount
 {-# INLINE someDiscreteAmount #-}
 
--- | Internal. Build a 'SomeDiscrete' from raw values.
+-- | Build a 'SomeDiscrete' from raw values.
 --
 -- This function is intended for deserialization purposes. You need to convert
 -- this 'SomeDiscrete' value to a 'Discrete' vallue in order to do any
@@ -1017,8 +1064,8 @@
   => SomeDiscrete
   -> Maybe (Discrete' currency scale)  -- ^
 fromSomeDiscrete = \dr ->
-   if (_someDiscreteCurrency dr == symbolVal (Proxy @ currency)) &&
-      (someDiscreteScale dr == scale (Proxy @ scale))
+   if (_someDiscreteCurrency dr == symbolVal (Proxy @currency)) &&
+      (someDiscreteScale dr == scale (Proxy @scale))
    then Just (Discrete (someDiscreteAmount dr))
    else Nothing
 {-# INLINABLE fromSomeDiscrete #-}
@@ -1119,7 +1166,7 @@
 someExchangeRateRate = _someExchangeRateRate
 {-# INLINE someExchangeRateRate #-}
 
--- | Internal. Build a 'SomeExchangeRate' from raw values.
+-- | Build a 'SomeExchangeRate' from raw values.
 --
 -- This function is intended for deserialization purposes. You need to convert
 -- this 'SomeExchangeRate' value to a 'ExchangeRate' value in order to do any
@@ -1160,8 +1207,8 @@
   => SomeExchangeRate
   -> Maybe (ExchangeRate src dst)  -- ^
 fromSomeExchangeRate = \x ->
-   if (_someExchangeRateSrcCurrency x == symbolVal (Proxy @ src)) &&
-      (_someExchangeRateDstCurrency x == symbolVal (Proxy @ dst))
+   if (_someExchangeRateSrcCurrency x == symbolVal (Proxy @src)) &&
+      (_someExchangeRateDstCurrency x == symbolVal (Proxy @dst))
    then Just (ExchangeRate (someExchangeRateRate x))
    else Nothing
 {-# INLINABLE fromSomeExchangeRate #-}
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -72,6 +72,7 @@
   Tasty.testGroup "root"
   [ testCurrencies
   , testHalfEvenRounding
+  , testHalfAwayFromZeroRounding
   , testCurrencyUnits
   , testExchange
   , testRationalToDecimal
@@ -1135,6 +1136,42 @@
     f :: Rational -> Integer
     f = MoneyI.approximate MoneyI.HalfEven
 
+testHalfAwayFromZeroRounding :: Tasty.TestTree
+testHalfAwayFromZeroRounding =
+    Tasty.testGroup "HalfAwayFromZero rounding"
+    [ HU.testCase "-2.8" $ -3 @=? f (-3152519739159347 % 1125899906842624)
+
+    , HU.testCase "-2.5" $ -3 @=? f (-5 % 2)
+    , HU.testCase "-2.2" $ -2 @=? f (-2476979795053773 % 1125899906842624)
+    , HU.testCase "-2"   $ -2 @=? f (-2 % 1)
+    , HU.testCase "-1.8" $ -2 @=? f (-8106479329266893 % 4503599627370496)
+    , HU.testCase "-1.5" $ -2 @=? f (-3 % 2)
+
+    , HU.testCase "-1.2" $ -1 @=? f (-5404319552844595 % 4503599627370496)
+    , HU.testCase "-1"   $ -1 @=? f (-1 % 1)
+    , HU.testCase "-0.8" $ -1 @=? f (-3602879701896397 % 4503599627370496)
+
+    , HU.testCase "-0.5" $  -1 @=? f (-1 % 2)
+    , HU.testCase "-0.2" $  0 @=? f (-3602879701896397 % 18014398509481984)
+    , HU.testCase  "0"   $  0 @=? f (0 % 1)
+    , HU.testCase  "0.2" $  0 @=? f (3602879701896397 % 18014398509481984)
+    , HU.testCase  "0.5" $  1 @=? f (1 % 2)
+
+    , HU.testCase  "0.8" $  1 @=? f (3602879701896397 % 4503599627370496)
+    , HU.testCase  "1"   $  1 @=? f (1 % 1)
+    , HU.testCase  "1.2" $  1 @=? f (5404319552844595 % 4503599627370496)
+
+    , HU.testCase  "1.5" $  2 @=? f (3 % 2)
+    , HU.testCase  "1.8" $  2 @=? f (8106479329266893 % 4503599627370496)
+    , HU.testCase  "2"   $  2 @=? f (2 % 1)
+    , HU.testCase  "2.2" $  2 @=? f (2476979795053773 % 1125899906842624)
+    , HU.testCase  "2.5" $  3 @=? f (5 % 2)
+
+    , HU.testCase  "2.8" $  3 @=? f (3152519739159347 % 1125899906842624)
+    ]
+  where
+    f :: Rational -> Integer
+    f = MoneyI.approximate MoneyI.HalfAwayFromZero
 
 
 -- | Decimal dot, 2 decimals
