implementation of BigDecimal in idris - decimal

I'm trying to implement a bigdecimal in Idris. I have this so far:
-- a big decimal has a numerator and a 10^x value
-- it has one type for zero,
--TODO the numerator can't be zero for any other case
--TODO and it can't be divisible by 10
data BigDecimal : (num : Integer) -> (denExp : Integer) -> Type where
Zero : BigDecimal 0 0
BD : (n : Integer) -> (d : Integer) -> BigDecimal n d
I would like to force the restrictions marked by "TODO" above. However, I'm am just learning Idris, so I'm not even sure if this sort of restriction is a good idea or not.
In general I'm trying to create a tax calculation tool capable of computing with multiple (crypto)currencies using arbitrary precision. I'd like to be able to then try and use the prover to prove some properties about the program.
So, my questions are:
Is it a good design decision to try to enforce the restrictions I have specified?
Is it possible to do this kind of restriction in Idris?
Is this a good implementation of a BigDecimal in Idris?
Edit: I was thinking of something like "BD : (n : Integer) -> ((n = 0)=Void) -> (d : Integer) -> BigDecimal n d", so you have to pass a proof that n isn't zero. But I really don't know if this is a good idea or not.
Edit 2: In response to Cactus's comment, would this be better?
data BigDecimal : Type where
Zero : BigDecimal
BD : (n : Integer) -> (s : Integer) -> BigDecimal

You could just spell out your invariants in the constructor types:
data BigDecimal: Type where
BDZ: BigDecimal
BD: (n : Integer) -> {auto prf: Not (n `mod` 10 = 0)} -> (mag: Integer) -> BigDecimal
Here, prf will ensure that n is not divisible by 10 (which also means it will not be equal to 0), thereby ensuring canonicity:
The only representation of 0 is BDZ
The only representation of n * 10mag is BD n mag:
BD (n * 10) (mag - 1) is rejected because n * 10 is divisible by 10, and since n itself is not divisible by 10, BD (n / 10) (mag + 1) would not work either.
EDIT: It turns out, because Integer division is non-total, Idris doesn't reduce the n `mod` 10 in the type of the constructor BD, so even something as simple as e.g. BD 1 3 doesn't work.
Here's a new version that uses Natural numbers, and Data.Nat.DivMod, to do total divisibility testing:
-- Local Variables:
-- idris-packages: ("contrib")
-- End:
import Data.Nat.DivMod
import Data.So
%default total
hasRemainder : DivMod n q -> Bool
hasRemainder (MkDivMod quotient remainder remainderSmall) = remainder /= 0
NotDivides : (q : Nat) -> {auto prf: So (q /= 0)} -> Nat -> Type
NotDivides Z {prf = Oh} n impossible
NotDivides (S q) n = So (hasRemainder (divMod n q))
Using this, we can use a Nat-based representation of BigDecimal:
data Sign = Positive | Negative
data BigNatimal: Type where
BNZ: BigNatimal
BN: Sign -> (n : Nat) -> {auto prf: 10 `NotDivides` n} -> (mag: Integer) -> BigNatimal
which is easy to work with when constructing BigNatimal values; e.g. here's 1000:
bn : BigNatimal
bn = BN Positive 1 3
EDIT 2: Here's a try at converting Nats into BigNatimals. It works, but Idris doesn't see fromNat' as total.
tryDivide : (q : Nat) -> {auto prf : So (q /= 0)} -> (n : Nat) -> Either (q `NotDivides` n) (DPair _ (\n' => n' * q = n))
tryDivide Z {prf = Oh} n impossible
tryDivide (S q) n with (divMod n q)
tryDivide _ (quot * (S q)) | MkDivMod quot Z _ = Right (quot ** Refl)
tryDivide _ (S rem + quot * (S q)) | MkDivMod quot (S rem) _ = Left Oh
fromNat' : (n : Nat) -> {auto prf: So (n /= 0)} -> DPair BigNatimal NonZero
fromNat' Z {prf = Oh} impossible
fromNat' (S n) {prf = Oh} with (tryDivide 10 (S n))
fromNat' (S n) | Left prf = (BN Positive (S n) {prf = prf} 1 ** ())
fromNat' _ | Right (Z ** Refl) impossible
fromNat' _ | Right ((S n') ** Refl) with (fromNat' (S n'))
fromNat' _ | Right _ | (BNZ ** nonZero) = absurd nonZero
fromNat' _ | Right _ | ((BN sign k {prf} mag) ** _) = (BN sign k {prf = prf} (mag + 1) ** ())
fromNat : Nat -> BigNatimal
fromNat Z = BNZ
fromNat (S n) = fst (fromNat' (S n))

Related

How does list generation with Fractionals work? [duplicate]

This question already has answers here:
Haskell ranges and floats
(2 answers)
Is floating point math broken?
(31 answers)
Closed 4 years ago.
If i want to generate a list with the input:
[3.1,5.1..8.1]
GHC 8.6.3 returns:
[3.1,5.1,7.1,9.099999999999998]
My problem here isn't the approximation of 9.1, but why the list made by GHC has one element more than the following solution.
In the documentation I found in GHC.Enum, that enumFromThenTo translates this to something similar to the following:
-- | Used in Haskell's translation of #[n,n'..m]# with
-- #[n,n'..m] = enumFromThenTo n n' m#, a possible implementation
-- being #enumFromThenTo n n' m = worker (f x) (c x) n m#,
-- #x = fromEnum n' - fromEnum n#, #c x = bool (>=) (<=) (x > 0)#
-- #f n y
-- | n > 0 = f (n - 1) (succ y)
-- | n < 0 = f (n + 1) (pred y)
-- | otherwise = y# and
-- #worker s c v m
-- | c v m = v : worker s c (s v) m
-- | otherwise = []#
So the following code:
import Data.Bool
eftt n s m = worker (f x) (c x) n m
where x = (fromEnum s) - (fromEnum n)
c x = bool (>=) (<=) (x > 0)
f n y
| n > 0 = f (n-1) (succ y)
| n < 0 = f (n+1) (pred y)
| otherwise = y
worker s c v m
| c v m = v: worker s c (s v) m
| otherwise = []
On the same input as before, this however returns this list:
[3.1,5.1,7.1]
The real implementation defined in GHC.Enum is the following:
enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]
But there is no instantiation of Enum Double or Enum Float in GHC.Enum
So when I tried to reproduce this with the following code:
import Prelude(putStrLn,show)
import GHC.Enum(toEnum,fromEnum,Enum,enumFromThenTo)
import GHC.Base(map)
main = putStrLn (show (_enumFromThenTo 3.1 5.1 8.1))
_enumFromThenTo :: (Enum a) => a -> a -> a -> [a]
_enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]
I compiled with:
$ ghc -package ghc -package base <file.hs>
The result was again:
[3.0,5.0,7.0]
What is happening here, such that the output becomes:
[3.1,5.1,7.1,9.099999999999998]
?
Well, this is instance Enum Double
instance Enum Double where
enumFromThenTo = numericEnumThenFromTo
The implementation is here
numericEnumFromThenTo :: (Ord a, Fractional a) => a -> a -> a -> [a]
numericEnumFromThenTo e1 e2 e3
= takeWhile predicate (numericEnumFromThen e1 e2)
where
mid = (e2 - e1) / 2
predicate | e2 >= e1 = (<= e3 + mid)
| otherwise = (>= e3 + mid)
More important than the implementation is the note above it:
-- These 'numeric' enumerations come straight from the Report
Which refers to this passage in the (2010) Report:
For Float and Double, the semantics of the enumFrom family is given by the rules for Int above, except that the list terminates when the elements become greater than e3 + i∕2 for positive increment i, or when they become less than e3 + i∕2 for negative i.
(Where e3 refers to the upper bound, and i the increment.)
The comment you found on Enum and the implementation in class Enum are both irrelevant. The comment is just example code detailing how an instance might be implemented, and the implementation given is inside a class, and thus may be overridden with anything.

Majority logic decoding Haskell

I have to calculate the probability of the proper decoding of a bit copied n times.
The following formula is supposed to be the answer:
In Haskell, I coded it as follows:
fac 1 = 1
fac n = fac (n-1) * n
--prob :: (Integral b, Fractional b) => (b, b) -> b
--prob :: (Int,Int) -> Double
prob (n, k)
| n==k = (0.01**k)
| otherwise = factor (n, k) * (0.01 ** k) * (0.99**(n-k)) + prob (n, (k+1))
where
factor (n, k) = (fac n / ((fac k)* (fac n-k)))
1 - prob (3,2) gives the result 0.99992575, which is incorrect, as it should be 0.99970. Does anyone know where I went wrong?
The reason is function precedence.
if you would look into the definition of prob you will see this:
(fac n-k)
because function application has the most precedence this is parsed as
((fac n) - k)
so your code should be
(fac (n-k))
which gives a result of 0.999702 on my computer.
These are a couple of best-practices the code is lacking. I infact already answered the question itself.
1- do not use tuples as input. in Haskell, functions can have multiple parameters. the syntax is f x y for calling f on x and y. the types also have similar syntax. this transforms your code to:
fac 1 = 1
fac n = fac (n-1) * n
--prob :: (Integral b, Fractional b) => b -> b -> b (two parameters of type b and output of type b)
--prob :: Int -> Int -> Double
prob n k
| n==k = (0.01**k)
| otherwise = factor n k * (0.01 ** k) * (0.99**(n-k)) + prob n (k+1)
where
factor n k = (fac n / ((fac k)* (fac (n-k))))
2- if you will notice, fac will only work on Integers, and similarly does factor. prob infact then has type of (Fractional a, Integral b) -> b -> b -> a or alternatively Integer -> Integer -> Float. why not give them their true type?
this transformation requires changing ** (which gets two floating point numbers) to ^ (which gets an Integer as it's second parameter) and using the function fromIntegral which casts an Integer to an arbitrary number Data.
fac :: Integral a => a -> a -- or alternatively Integer -> Integer
fac 1 = 1
fac n = fac (n-1) * n
prob n k
| n==k = (0.01 ^^ k)
| otherwise = fromIntegral (factor n k) * (0.01 ^^ k) * (0.99 ^^ (n-k) + prob n (k+1)
where
factor n k = div (fac n) (fac k * fac (n-k)) -- div is Integer division operator.
now prob has type of (Integral a, Floating b) => a -> a -> b which means it gets two parameters of type a (which is an Integral instance) and returns a value of type b.

Type declaration for number division

I tried all possible type declarations but I can't make this code even compile. The trick is in handling types for division. I tried Num a, Fractional a, Float a etc.
cube x = x * x * x
sum' term a next b =
if a > b
then 0
else term a + sum' term (next a) next b
integral f a b n = (h / 3) * (sum' term 0 succ n) where
h = (b - a) / n
y k = f $ a + (k * h)
term k
| k == 0 || k == n = y k
| odd k = 4 * y k
| even k = 2 * y k
main = do
print $ integral cube 0 1 100 -- 0.25
print $ (\x -> 3 * x * x) 1 3 100 -- 26
I isolated problem by deleting (/) function. This code compiles without any type declaration at all:
cube x = x * x * x
sum' term a next b =
if a > b
then 0
else term a + sum' term (next a) next b
integral f a b n = (sum' term 0 succ n) where
h = (b - a)
y k = f $ a + (k * h)
term k
| k == 0 || k == n = y k
| odd k = 4 * y k
| even k = 2 * y k
main = do
print $ integral cube 0 1 100
Another question is how to debug cases like this? Haskell's error messages doesn't help much, it's kind of hard to understand something like The type variable a0 is ambiguous or Could not deduce (a1 ~ a).
P. S. It's ex. 1.29 from SICP.
Update
Final answer is:
cube :: Num a => a -> a
cube x = x * x * x
sum' :: (Int -> Double) -> Int -> (Int -> Int) -> Int -> Double
sum' term a next b =
if a > b
then 0
else term a + sum' term (next a) next b
integral :: (Double -> Double) -> Double -> Double -> Int -> Double
integral f a b n = (h / 3) * sum' term 0 (+1) n where
h = (b - a) / n' where n' = fromIntegral n
y k = f $ a + (k * h)
term k
| k == 0 || k == n = y k'
| odd k = 4 * y k'
| even k = 2 * y k'
where k' = fromIntegral k
main = do
print $ integral cube 0 1 100 -- 0.25
print $ integral cube 0 1 1000 -- 0.25
print $ integral (\x -> 3 * x * x) 1 3 100 -- 26
/ is only used for types that are instances of Fractional, for Integral types use quot. You can use quot as an infix operator using backticks:
h = (b - a) `quot` n
The types of the two are
(/) :: Fractional a => a -> a -> a
quot :: Integral a => a -> a -> a
There are no types that are instances of both Fractional and Integral, which is why none of the type signatures would work. Unfortunately GHC doesn't know that it's impossible for a type to be an instance of both classes, so the error messages are not very intuitive. You get used to the style of GHC error messages though, and the detail they give helps a lot.
Also, as was suggested in the comments, I completely agree that all top level definitions should be given type signatures (including main). It makes error messages a lot easier to read.
Edit: Based on the comments below, it looks like what you want is something more like this (type signature-wise)
cube :: Num a => a -> a
sum' :: (Int -> Double) -> Int -> (Int -> Int) -> Int -> Double
integral :: (Double -> Double) -> Double -> Double -> Int -> Double
You will need to use fromIntegral to convert from Int to Double in h and in k. The type errors should be at least a bit more readable with these type signatures though.

Implementing Wiener's Algorithm in Haskell - No instance for (RealFrac a0) arising from a use of `wiener'

I'm trying to implement in Haskell the Wiener's Algorithm from the book Cryptography: Theory and Practice, Third Edition. Here's what I've written so far:
import Data.List
wiener e n = factors
where euclid = euclidean e n
cs = 1 : head euclid : rest cs euclid
ds = 0 : 1 : rest ds euclid
ns = filter isInt $ drop 2 $ zipWith (\x y -> (x * e - 1) / y) ds cs
qs = map (\x -> quad 1 (x - n - 1) n) ns
factors = find (\(p, q) -> isInt p && 0 < p && p < n
&& isInt q && 0 < q && q < n) qs
rest xs ys = zipWith (+) xs (zipWith (*) (tail ys) (tail xs))
euclidean _ 0 = []
euclidean a b = a `div` b : euclidean b (a `mod` b)
quad a b c
| d > 0 = ((-b + sqrt d) / (2 * a), (-b - sqrt d) / (2 * a))
| otherwise = (0.0, 0.0)
where d = b * b - 4 * a * c
isInt x = x == fromInteger (round x)
Trying wiener 238123333 293719721 gives me:
No instance for (RealFrac a0) arising from a use of `wiener'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
No instance for (Num a0) arising from the literal `238123333'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s
How should I proceed? Is there any general number type such that it can be used everywhere?
I tracked down the error. The return type of euclidean is Integral a => [a] while quad returns an instance of RealFrac. Since you use the value n and e as arguments to both functions, n and e must be instances of both typeclasses.
wiener :: (Floating b, Integral a, RealFrac b) => a -> a -> Maybe (b,b)
wiener e' n' = factors
where euclid = map fromIntegral $ euclidean e' n' -- convert result from `Integral` to `Num`
e = fromIntegral e' -- convert Integral to Num
n = fromIntegral n'
cs = 1 : head euclid : rest cs euclid
ds = 0 : 1 : rest ds euclid
ns = filter isInt $ drop 2 $ zipWith (\x y -> (x * e - 1) / y) ds cs
qs = map (\x -> quad 1 (x - n - 1) n) ns
factors = find (\(p, q) -> isInt p && 0 < p && p < n
&& isInt q && 0 < q && q < n) qs
rest xs ys = zipWith (+) xs (zipWith (*) (tail ys) (tail xs))

Use QuickCheck by generating primes

Background
For fun, I'm trying to write a property for quick-check that can test the basic idea behind cryptography with RSA.
Choose two distinct primes, p and q.
Let N = p*q
e is some number relatively prime to (p-1)(q-1) (in practice, e is usually 3 for fast encoding)
d is the modular inverse of e modulo (p-1)(q-1)
For all x such that 1 < x < N, it is always true that (x^e)^d = x modulo N
In other words, x is the "message", raising it to the eth power mod N is the act of "encoding" the message, and raising the encoded message to the dth power mod N is the act of "decoding" it.
(The property is also trivially true for x = 1, a case which is its own encryption)
Code
Here are the methods I have coded up so far:
import Test.QuickCheck
-- modular exponentiation
modExp :: Integral a => a -> a -> a -> a
modExp y z n = modExp' (y `mod` n) z `mod` n
where modExp' y z | z == 0 = 1
| even z = modExp (y*y) (z `div` 2) n
| odd z = (modExp (y*y) (z `div` 2) n) * y
-- relatively prime
rPrime :: Integral a => a -> a -> Bool
rPrime a b = gcd a b == 1
-- multiplicative inverse (modular)
mInverse :: Integral a => a -> a -> a
mInverse 1 _ = 1
mInverse x y = (n * y + 1) `div` x
where n = x - mInverse (y `mod` x) x
-- just a quick way to test for primality
n `divides` x = x `mod` n == 0
primes = 2:filter isPrime [3..]
isPrime x = null . filter (`divides` x) $ takeWhile (\y -> y*y <= x) primes
-- the property
prop_rsa (p,q,x) = isPrime p &&
isPrime q &&
p /= q &&
x > 1 &&
x < n &&
rPrime e t ==>
x == (x `powModN` e) `powModN` d
where e = 3
n = p*q
t = (p-1)*(q-1)
d = mInverse e t
a `powModN` b = modExp a b n
(Thanks, google and random blog, for the implementation of modular multiplicative inverse)
Question
The problem should be obvious: there are way too many conditions on the property to make it at all usable. Trying to invoke quickCheck prop_rsa in ghci made my terminal hang.
So I've poked around the QuickCheck manual a bit, and it says:
Properties may take the form
forAll <generator> $ \<pattern> -> <property>
How do I make a <generator> for prime numbers? Or with the other constraints, so that quickCheck doesn't have to sift through a bunch of failed conditions?
Any other general advice (especially regarding QuickCheck) is welcome.
Here's one way to make a QuickCheck-compatible prime-number generator (stealing a Sieve of Eratosthenes implementation from http://en.literateprograms.org/Sieve_of_Eratosthenes_(Haskell)):
import Test.QuickCheck
newtype Prime = Prime Int deriving Show
primes = sieve [2..]
where
sieve (p:xs) = Prime p : sieve [x | x <- xs, x `mod` p > 0]
instance Arbitrary Prime where
arbitrary = do i <- arbitrary
return $ primes!!(abs i)
It can be used in QuickCheck like so:
prop_primes_dont_divide (Prime x) (Prime y) = x == y || x `mod` y > 0
For your use, you'd replace p and q with (Prime p) and (Prime q) in your property.
OK so here's what I did.
Top of file
{-# LANGUAGE NoMonomorphismRestriction #-}
import Test.QuickCheck
import Control.Applicative
All code as given in the question, except for prop_rsa. That was (obviously) heavily modified:
prop_rsa = forAll primePair $ \(p,q) ->
let n = p*q
in forAll (genUnder n) $ \x ->
let e = 3
t = (p-1)*(q-1)
d = mInverse e t
a `powModN` b = modExp a b n
in p /= q &&
rPrime e t ==>
x == (x `powModN` e) `powModN` d
The type for primePair is Gen (Int, Int), and the type for genUnder is Int -> Gen Int. I'm not exactly sure what the magic is behind forAll but I'm pretty sure this is correct. I've done some ad-hoc adjustments to 1) make sure it fails if I mess up the conditions and 2) make sure the nested forAll is varying the value of x across test cases.
So here's how to write those generators. Once I realized that <generator> in the documentation just meant something of type Gen a, it was cake.
genNonzero = (\x -> if x == 0 then 1 else x) `fmap` arbitrary
genUnder :: Int -> Gen Int
genUnder n = ((`mod` n) . abs) `fmap` genNonzero
genSmallPrime = ((\x -> (primes !! (x `mod` 2500))) . abs) `fmap` arbitrary
primePair :: Gen (Int, Int)
primePair = (,) <$> genSmallPrime <*> genSmallPrime
primePair took some trial and error for me to get right; I knew that some combinators like that should work, but I'm still not as familiar with fmap, <$> and <*> as I'd like to be. I restricted the computation to only select from among the first 2500 primes; otherwise it apparently wanted to pick some really big ones that took forever to generate.
Random thing to note
Thanks to laziness, d = mInverse e t isn't computed unless the conditions are met. Which is good, because it's undefined when the condition rPrime e t is false. In English, an integer a only has a multiplicative inverse (mod b) when a and b are relatively prime.

Resources