packages feed

AFSM-0.1.3.0: examples/Toys.hs

-----------------------------------------------------------------------------
-- Copyright   :  (c) Hanzhong Xu, Meng Meng 2016,
-- License     :  MIT License
--
-- Maintainer  :  hanzh.xu@gmail.com
-- Stability   :  experimental
-- Portability :  portable
-----------------------------------------------------------------------------
-- A collection of toys
-----------------------------------------------------------------------------

module Toys where

-- import System.Random
import Data.Tuple

import Data.Sequence (Seq, empty, (|>), ViewL(..), viewl)

import Control.AFSM
import Control.AFSM.Event

----------
-- Fibs --
----------

-- the nice code from experts.
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

-- make beginners' life easier.
--   the SM stores f_n and f_{n+1},
--   for each time we update the storage to (f_{n+1}, f_n + f_{n+1}),
--   and outputs f_n.
fibsSM :: SM (Int, Int) () Int
fibsSM = simpleSM (\(a, b) () -> ((b, a+b), a)) (0, 1)

ourfibs = simpleSrc fibsSM

-------------------
-- Random Source --
-------------------
{-
randSM :: StdGen -> SM StdGen () Int
randSM = simpleSM (\g () -> swap $ next g)

randSrc :: Int -> [Int]
randSrc = simpleSrc.randSM.mkStdGen

randSamples = take 5 $ randSrc 111
-}
-------------------
-- Prime Numbers --
-------------------

ltest :: [Int] -> Int -> Bool
ltest [] _ = True
ltest (x:xs) a = if mod a x == 0 then False else if x * x > a then True else ltest xs a

-- [2,3,5,...]
-- origin_primes = filter (ltest origin_primes) [2..]
-- The problem is the first prime number should be given by hand.
origin_primes = 2:(filter (ltest origin_primes) [3..])

seqtest :: (ViewL Int) -> Int -> Bool
seqtest EmptyL _ = True
seqtest (x :< sq) a = if mod a x == 0 then False else if x * x > a then True else seqtest (viewl sq) a


-- The storage maintains a list of prime numbers it has known so far.
-- Here we use Seq as the storage, it is similar with list, but has more efficient append operation.
-- When a new number comes, the SM test the number with the list, if it pass the test, then add it into the list, else drop it.
primeSM :: SM (Seq Int) Int (Event Int)
primeSM = simpleSM f empty
  where
    f sq a =
      if seqtest (viewl sq) a then
        (sq |> a, Event a)
      else
        (sq, NoEvent)

-- [2,3,5,...]
primes = extractEvents $ smfmap (primeSM) [2..]

--