primes-type (empty) → 0.2.0.0
raw patch · 5 files changed
+226/−0 lines, 5 filesdep +HTFdep +basedep +primessetup-changed
Dependencies added: HTF, base, primes, primes-type
Files
- LICENSE +15/−0
- Setup.hs +2/−0
- primes-type.cabal +47/−0
- src/Data/Numbers/Primes/Type.hs +59/−0
- test/Spec.hs +103/−0
+ LICENSE view
@@ -0,0 +1,15 @@+ISC License++Copyright (c) 2017, Ignat Insarov++Permission to use, copy, modify, and/or distribute this software for any+purpose with or without fee is hereby granted, provided that the above+copyright notice and this permission notice appear in all copies.++THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ primes-type.cabal view
@@ -0,0 +1,47 @@+-- This file has been generated from package.yaml by hpack version 0.17.1.+--+-- see: https://github.com/sol/hpack++name: primes-type+version: 0.2.0.0+synopsis: Type-safe prime numbers.+description: This library provides type safe prime numbers. The idea is based upon the concept of a predicate type from type theory.+category: Algorithms, Numerical+homepage: https://github.com/kindaro/primes-type#readme+bug-reports: https://github.com/kindaro/primes-type/issues+author: Ignat Insarov+maintainer: kindaro@gmail.com+copyright: 2017 Ignat Insarov+license: ISC+license-file: LICENSE+build-type: Simple+cabal-version: >= 1.10++source-repository head+ type: git+ location: https://github.com/kindaro/primes-type++library+ hs-source-dirs:+ src+ build-depends:+ base >=4.8 && <4.11+ , primes >=0.2 && <0.3+ exposed-modules:+ Data.Numbers.Primes.Type+ other-modules:+ Paths_primes_type+ default-language: Haskell2010++test-suite primes-type-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs:+ test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base >=4.8 && <5+ , primes >=0.2 && <0.3+ , primes-type+ , HTF >=0.13 && < 0.14+ default-language: Haskell2010
+ src/Data/Numbers/Primes/Type.hs view
@@ -0,0 +1,59 @@+{-# OPTIONS_GHC -funbox-strict-fields #-}++module Data.Numbers.Primes.Type+ ( Prime+ , getValue+ , getIndex+ , deconstruct+ , primeIndex+ , getPrime+ , maybePrime+ , indexedPrimes+ ) where++import Data.List (elemIndex)+import Data.Numbers.Primes++-- | An abstract type for primes.+--+-- It will only ever hold a valid prime, together with its zero-based index.+data Prime int = Prime { _value :: !int, _index :: !Int } deriving Show++-- | Given a Prime, give back its value.+getValue :: Prime int -> int+getValue = _value++-- | Given a Prime, give back its index.+getIndex :: Prime int -> Int+getIndex = _index++-- | Given a Prime, give back its value and index as a tuple.+deconstruct :: Prime int -> (int, Int)+deconstruct p = (_value p, _index p)++instance Integral int => Enum (Prime int) where+ toEnum = getPrime+ fromEnum = getIndex++instance Eq (Prime int) where+ x == y = getIndex x == getIndex y++instance Ord (Prime int) where+ x `compare` y = getIndex x `compare` getIndex y++-- | If a given number is prime, give its index.+primeIndex :: Integral n => n -> Maybe Int+primeIndex x | isPrime x = elemIndex x primes+ | otherwise = Nothing++-- | Give n-th prime.+getPrime :: Integral int => Int -> Prime int+getPrime n = Prime (primes !! n) n++-- | If a given number is prime, give it back wrapped as such.+maybePrime :: (Integral int) => int -> Maybe (Prime int)+maybePrime x = Prime x <$> primeIndex x++-- | A list of indexed primes.+indexedPrimes :: Integral int => [Prime int]+indexedPrimes = getPrime <$> [0,1..]
+ test/Spec.hs view
@@ -0,0 +1,103 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module Main where++import Test.Framework+import Data.Numbers.Primes+import Data.Numbers.Primes.Type+import Data.Word++instance (Arbitrary a, Integral a) => Arbitrary (Prime a) where+ arbitrary = getPrime <$> arbitrarySizedNatural++main = htfMain htf_thisModulesTests++-- | Some basic sanity checks.++test_prime = do+ assertEqual (Just $ getPrime 0) (maybePrime 2)+ assertEqual (Just $ getPrime 5) (maybePrime 13)+ assertEqual (primeIndex 2) (Just 0)+ assertEqual (primeIndex 13) (Just 5)+ assertEqual (maybePrime 4) (Nothing)++-- | These two properties show that Prime and its value are+-- isomorphic if and only if the value is prime.+-- (n in N but not in P are mapped to Nothing with no inverse.)++-- prop_maybePrime :: Integral int => int -> Bool -- ^ This is too general to suit a prop.+prop_maybePrime_Int = withQCArgs (\prop -> prop { maxSize = 1024 } ) prop_maybePrime_Int'+ where prop_maybePrime_Int' :: Int -> Bool+ prop_maybePrime_Int' x = r == Just x || r == Nothing+ where r :: Maybe Int+ r = getValue <$> maybePrime x++prop_maybePrime_Integer = withQCArgs (\prop -> prop { maxSize = 1024 } ) prop_maybePrime_Integer'+ where prop_maybePrime_Integer' :: Integer -> Bool+ prop_maybePrime_Integer' x = r == Just x || r == Nothing+ where r :: Maybe Integer+ r = getValue <$> maybePrime x++prop_maybePrime_Word = withQCArgs (\prop -> prop { maxSize = 5 } ) prop_maybePrime_Word'+ where prop_maybePrime_Word' :: Word8 -> Bool+ prop_maybePrime_Word' x = r == Just x || r == Nothing+ where r :: Maybe Word8+ r = getValue <$> maybePrime x++prop_getValue_Int = withQCArgs (\prop -> prop { maxSize = 1024 } ) prop_getValue_Int'+ where+ prop_getValue_Int' :: Int -> Bool+ prop_getValue_Int' n = (maybePrime . getValue $ p) == Just p+ where+ p :: Prime Int+ p | n < 0 = getPrime . abs $ n -- I know it's not super bright.+ | otherwise = getPrime n++-- | These two properties show that Prime and its index are isomorphic.++prop_primeIndex :: Int -> Bool+prop_primeIndex n = m == (getIndex <$> getPrime) m+ where m = abs n++prop_getIndex :: Int -> Bool+prop_getIndex n = getPrime m == (getPrime . getIndex . getPrime) m+ where m = abs n++-- | This property verifies the correctness of `deconstruct`.++prop_deconstruct i = deconstruct p == (getValue p, getIndex p)+ where+ p = getPrime (abs i)++-- | These two properties show that the enumeration associated with Prime is isomorphic.++prop_fromEnum :: Prime Int -> Bool+prop_fromEnum p = p == (toEnum . fromEnum) p++prop_toEnum :: Int -> Bool+prop_toEnum n' = n == (fromEnum . (toEnum :: Int -> Prime Int)) n+ where+ n = abs n'++-- | Equality & ordering of primes is the same as the respective relations on their indices.++prop_Eq = withQCArgs (\prop -> prop { maxSize = 256 } ) prop_Eq'+ where+ prop_Eq' :: (Int, Int) -> Bool+ prop_Eq' (i', j') = (i == j) == (getPrime i == getPrime j)+ where+ i = abs i'+ j = abs j'++prop_compare = withQCArgs (\prop -> prop { maxSize = 256 } ) prop_compare'+ where+ prop_compare' :: (Int, Int) -> Bool+ prop_compare' (i', j') = i `compare` j == (getPrime i `compare` getPrime j)+ where+ i = abs i'+ j = abs j'++-- | The list of indexed primes corresponds to its unzips.+test_indexedPrimes = assertEqual+ (deconstruct <$> take 100 indexedPrimes)+ (take 100 $ zip primes [0..])