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..]
--