Skip to content

Instantly share code, notes, and snippets.

@jpablo
Last active November 24, 2016 18:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpablo/b01c56c74c84395b886f63baf01a905f to your computer and use it in GitHub Desktop.
Save jpablo/b01c56c74c84395b886f63baf01a905f to your computer and use it in GitHub Desktop.
IO Monad, Random numbers in Haskell
-- required: stack install random
import System.Random
-------- Fermat test -----------------
expmod base e m
| e == 0 = 1
| even e = mod (expmod base (e `div` 2) m ^ 2) m
| otherwise = mod (base * expmod base (e - 1) m) m
-- just to mimic the book
-- random between 1 and n inclusive
random' :: Int -> IO Int
random' n = randomRIO (1, n :: Int)
-- Scala: random': Int => IO[Int]
-- since random' is a monadic function (the result is wrappend inside a Monad)
-- we need to use a do notation (similar to Scala's for comprehension)
fermatTest :: Int -> IO Bool
fermatTest n = do
r <- random' $ n-1
return $ tryIt r
where
tryIt a = expmod a n n == a
-- Scala:
--
-- def fermatTest(n: Int): IO[Bool] = {
-- def tryIt(a: Int) = expmod(a,n,n) == a
-- for (r <- random'(n-1)) yield tryIt(r)
-- }
fastPrime n 0 = return True
fastPrime n times = do
t <- fermatTest n
if t then fastPrime n (times-1) else return False
--------- IO Monad ------------
-- rIO = randomRIO(1,10 :: Int)
-- fmap (+1) $ rIO == (+1) <$> rIO
-- alternative versions without do notation
-- fmap f b == f <$> b
-- using where
fermatTest' n = tryIt <$> random' (n-1)
where
tryIt a = expmod a n n == a
-- using let / in
fermatTest'' n =
let tryIt a = expmod a n n == a
in tryIt <$> random' (n-1)
fermatTest''' n = (\a -> expmod a n n == a) <$> random' (n-1)
-- Scala:
-- def fermatTest(n: Int) = random(n-1).map(a => expmod(a,n,n) == a)
fastPrime' n 0 = return True
fastPrime' n times = fermatTest n >>= (\t -> if t then fastPrime n (times-1) else return False)
-- Scala:
-- def fastPrime(n: Int, times: Int): IO[Bool] = fermatTest(n).flatMap(t => if (t) fastPrime(n, times-1) else IO(false))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment