diff --git a/src/lib/Witch/Instances.hs b/src/lib/Witch/Instances.hs index 7a33c17..7fc219e 100644 --- a/src/lib/Witch/Instances.hs +++ b/src/lib/Witch/Instances.hs @@ -1,6 +1,7 @@ {-# OPTIONS_GHC -Wno-orphans #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} module Witch.Instances where @@ -907,6 +908,16 @@ instance From.From Rational Float where instance From.From Rational Double where from = fromRational +-- | Uses `fromRational` as long as there isn't a loss of precision. +instance Fixed.HasResolution a => TryFrom.TryFrom Rational (Fixed.Fixed a) where + tryFrom = Utility.eitherTryFrom $ \s -> + let + t :: Fixed.Fixed a + t = fromRational s + in if toRational t == s + then Right t + else Left Exception.LossOfPrecision + -- Fixed -- | Uses 'Fixed.MkFixed'. This means @from \@Integer \@Centi 2@ is @0.02@ @@ -919,6 +930,10 @@ instance From.From Integer (Fixed.Fixed a) where instance From.From (Fixed.Fixed a) Integer where from (Fixed.MkFixed t) = t +-- | Uses 'toRational'. +instance Fixed.HasResolution a => From.From (Fixed.Fixed a) Rational where + from = toRational + -- Complex -- | Uses '(Complex.:+)' with an imaginary part of 0. diff --git a/src/test/Main.hs b/src/test/Main.hs index 1b2ac2c..9bb1c89 100644 --- a/src/test/Main.hs +++ b/src/test/Main.hs @@ -1448,6 +1448,15 @@ main = runTestTTAndExit $ "Witch" ~: , f 0.5 ~?= 0.5 , f (-0.5) ~?= (-0.5) ] + , "TryFrom Rational (Fixed a)" ~: + let f = hush . Witch.tryFrom @Rational @Fixed.Deci in + [ hush (Witch.tryFrom @Rational @Fixed.Uni 1) ~?= Just 1 + , hush (Witch.tryFrom @Rational @Fixed.Uni 1.2) ~?= Nothing + , f 0.1 ~?= Just 0.1 + , f 1.2 ~?= Just 1.2 + , f 12.3 ~?= Just 12.3 + , f 0.12 ~?= Nothing + ] -- Fixed @@ -1455,11 +1464,22 @@ main = runTestTTAndExit $ "Witch" ~: let f = Witch.from @Integer @Fixed.Deci in [ Witch.from @Integer @Fixed.Uni 1 ~?= 1 , f 1 ~?= 0.1 + , f 10 ~?= 1 + , f 120 ~?= 12 ] , "From (Fixed a) Integer" ~: let f = Witch.from @Fixed.Deci @Integer in [ Witch.from @Fixed.Uni @Integer 1 ~?= 1 + , f 0.1 ~?= 1 , f 1 ~?= 10 + , f 12 ~?= 120 + ] + , "From (Fixed a) Rational" ~: + let f = Witch.from @Fixed.Deci @Rational in + [ Witch.from @Fixed.Uni @Rational 1 ~?= 1 + , f 0.1 ~?= 0.1 + , f 1 ~?= 1 + , f 12 ~?= 12 ] -- Complex