AFSM-0.1.3.0: examples/HelloWorld.hs
-----------------------------------------------------------------------------
-- Copyright : (c) Hanzhong Xu, Meng Meng 2016,
-- License : MIT License
--
-- Maintainer : hanzh.xu@gmail.com
-- Stability : experimental
-- Portability : portable
-----------------------------------------------------------------------------
-- HelloWorld
-----------------------------------------------------------------------------
{-# LANGUAGE PartialTypeSignatures #-}
module HelloWorld where
import Control.AFSM
import Control.AFSM.SMH
import Data.Maybe
-- | x_i donates the ith element of the input, y_i donates the ith element of the output.
-- $setup
-- >>> let test0 = [1,2,3,4]::[Int]
-- basic machines
-- | the sum of the history, y_n = \sum_{i=1}^n x_i
-- >>> smfmap sumSM test0
-- [1,3,6,10]
sumSM :: SM Int Int Int
sumSM = simpleSM (\s a -> (s+a, s+a)) 0
-- | y_n = x_n + 1
-- >>> smfmap plusOneSM test0
-- [2,3,4,5]
plusOneSM :: SM () Int Int
plusOneSM = simpleSM (\() a -> ((), a + 1)) ()
-- | y_n = x_n * 2
-- >>> smfmap timesTwoSM test0
-- [2,4,6,8]
timesTwoSM :: SM () Int Int
timesTwoSM = arrSM (\a -> a * 2)
-- combination machine
-- | y_n = \sum_{i=1}^n x_i * 2
-- >>> smfmap ttSM test0
-- [2,6,12,20]
ttSM = timesTwoSM >>>> sumSM
-- | y_n = (x_n + 1, x_n * 2)
-- >>> smfmap ptSM test0
-- [(2,2),(3,4),(4,6),(5,8)]
ptSM = plusOneSM &&&& timesTwoSM
-- |
-- >>> smfmap mergeOutSM [(2,2),(3,4),(4,6),(5,8)]
-- [4,7,10,13]
--
-- | y_n = (x_n + 1) + (x_n * 2)
-- >>> smfmap ((plusOneSM &&&& timesTwoSM) >>>> mergeOutSM) test0
-- [4,7,10,13]
mergeOutSM :: SM () (Int, Int) Int
mergeOutSM = arrSM (\(a,b)->a+b)
-- example 3
data StackOP = Push Int
| Pop
| Max
deriving Show
pushStk [] a = ([a], a)
pushStk s a = (a:s, a)
popStk [] = ([], 0)
popStk (x:xs) = (xs, x)
maxStk [] = ([], 0)
maxStk s = (s, maxList s)
maxList :: [Int] -> Int
maxList [] = 0
maxList (x:xs) = max x (maxList xs)
initial = []
{-
pushStk ([],[]) a = (([a],[a]), a)
pushStk ((x:xs), (y:ys)) a = if a >= y then ((a:x:xs, a:y:ys), a) else ((a:x:xs, y:ys), a)
popStk ([],[]) = (([],[]), 0)
popStk ((x:xs), (y:ys)) = if x == y then ((xs, ys), x) else ((xs, y:ys), x)
maxStk ([], []) = (([], []), 0)
maxStk ((x:xs), (y:ys)) = (((x:xs), (y:ys)), y)
initial = ([],[])
-}
sf s (Push a) = pushStk s a
sf s Pop = popStk s
sf s Max = maxStk s
-- | The stroage type is changing during switching the implementation.
-- There are three ways to handle this issue,
-- 1. Remove the type signature of maxSM
-- 2. Use hideStorage to hide the storage type
-- 3. Use the PartialTypeSignatures extension, leave a hole in the type signature.
-- Personaly, I prefer to use the third one,
-- because the input type and output type are decidable.
-- >>> smfmap maxSM [Push 5, Push 3, Push 2, Max, Push 7, Max, Pop, Max]
-- [5,3,2,5,7,7,7,5]
maxSM :: SM _ StackOP Int
maxSM = simpleSM sf initial
-- maxSM :: SM () StackOP Int
-- maxSM = hideStorage $ simpleSM sf initial