Guest User

Untitled

a guest
Feb 23rd, 2018
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.75 KB | None | 0 0
  1. {-# LANGUAGE PolyKinds #-}
  2. {-# LANGUAGE DataKinds #-}
  3. {-# LANGUAGE TypeFamilies #-}
  4. {-# LANGUAGE TypeOperators #-}
  5. {-# LANGUAGE GADTs #-}
  6. {-# LANGUAGE ConstraintKinds #-}
  7. {-# LANGUAGE UndecidableInstances #-}
  8.  
  9. module Data.DeferIsPrime where
  10.  
  11. import GHC.TypeLits
  12. import Data.Type.Equality
  13. import Data.Proxy
  14. import Unsafe.Coerce
  15. import Control.Applicative
  16.  
  17. type family Not (x :: Bool) where
  18. Not 'True = 'False
  19. Not 'False = 'True
  20.  
  21. type family (x :: Nat) % (y :: Nat) :: Nat where
  22. x % y = Mod' x y (y <=? x)
  23.  
  24. type family Mod' (x :: Nat) (y :: Nat) (xGeqY :: Bool) :: Nat where
  25. Mod' x y 'True = Mod' (x - y) y (y <=? (x - y))
  26. Mod' x y 'False = x
  27.  
  28. type IsPrime p = IsPrimeB p ~ 'True
  29.  
  30. type family IsPrimeB (p :: Nat) :: Bool where
  31. IsPrimeB 0 = 'False
  32. IsPrimeB 1 = 'False
  33. IsPrimeB 2 = 'True
  34. IsPrimeB p = IsPrimeB' p 3 (p % 2 == 0) (Not (3 ^ 2 <=? p))
  35.  
  36. type family IsPrimeB' (p :: Nat) (i :: Nat) (hasFactor :: Bool) (searchEnd :: Bool) where
  37. IsPrimeB' _ _ 'True _ = 'False
  38. IsPrimeB' _ _ _ 'True = 'True
  39. IsPrimeB' p i _ _ = IsPrimeB' p (i + 2) (p % i == 0) (Not ((i + 2) ^ 2 <=? p))
  40.  
  41. data SomeIsPrime where
  42. SomeIsPrime :: (KnownNat p, IsPrime p) => Proxy p -> SomeIsPrime
  43.  
  44. unsafeMagic :: Proxy p -> IsPrimeB p :~: 'True
  45. unsafeMagic _ = unsafeCoerce Refl
  46.  
  47. -- ここに型族のIsPrimeと同じ実装を書く
  48. isPrime :: KnownNat n => Proxy n -> Bool
  49. isPrime n = case natVal n of
  50. 0 -> False -- テスト用
  51. 1 -> True -- テスト用
  52. _ -> undefined
  53.  
  54. -- |
  55. -- >>> import Data.Maybe
  56. -- >>> isNothing $ deferIsPrime 0
  57. -- True
  58. -- >>> isNothing $ deferIsPrime 1
  59. -- False
  60. --
  61. deferIsPrime :: Integer -> Maybe SomeIsPrime
  62. deferIsPrime i = do
  63. n <- someNatVal i
  64. case n of
  65. SomeNat p | isPrime p -> case unsafeMagic p of
  66. Refl -> pure $ SomeIsPrime p
  67. _ -> empty
Add Comment
Please, Sign In to add comment