COALGEBRAS AND AUTOMATA ----------------------- That this document is literate Haskell which means that it is a mixture of actual runnable code and comments. (This web page used to have the wrong title. It has nothing to do with the differentiation of datatypes and it's not really suitable for non-functional programmers.) (Also, I've since learnt that all of my definitions of fold and unfold below can be wrapped up into a single pair of definitions. See, eg. http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/hodgp.pdf ) An unHTMLified version of this document is available at http://www.sigfpe.com/Computing/fold.lhs which you can run in hugs or ghc.
import Maybe |
class (Functor f) => Algebra f x where
fin :: (f x) -> x
|
instance Algebra Maybe Integer where
fin Nothing = 0
fin (Just a) = a+1
|
instance Algebra Maybe Float where fin Nothing = 1.0 fin (Just x) = 2.0*x |
p :: Integer -> Float p n = 1.0*2^n |
ex0 = map (fin . (fmap p)) [Nothing,Just 0,Just 1,Just 16] ex1 = map (p . fin) [Nothing,Just 0,Just 1,Just 16] |
class (Algebra f x) => Initial f x | x -> f where
fold :: (f y -> y) -> (x -> y)
|
fout :: x -> (f x)
fout = fold (fmap fin)
|
instance Initial Maybe Integer where
fold f 0 = f Nothing
fold f (n+1) = f $ Just $ fold f n
|
--ex2 = fin $ fout $ (4::Integer) |
ex2 = map (fin . fout) [0,1,16 :: Integer] ex3 = map (fout . fin) [Nothing,Just 0,Just 1,Just 16 :: Maybe Integer] |
class (Functor f) => Coalgebra f x where
outf :: x -> f x
|
class (Coalgebra f x) => Final f x | x -> f where
unfold :: (y -> f y) -> (y -> x)
|
inf :: (f x) -> x
inf = unfold (fmap outf)
|
collatz :: Integer -> Maybe Integer
collatz 1 = Nothing
collatz n
| even n = Just $ n `div` 2
| odd n = Just $ 3*n+1
|
instance Coalgebra Maybe Integer where outf n = collatz n |
count f x = case f x of
Nothing -> 0
Just x -> 1+count f x
|
data Count = Infinity | Natural Integer deriving (Show) plusOne (Natural n) = Natural (1+n) plusOne Infinity = Infinity |
instance Coalgebra Maybe Count where
outf (Natural 0) = Nothing
outf (Natural (x+1)) = Just $ Natural x
outf Infinity = Just Infinity
|
instance Final Maybe Count where
unfold f x = case f x of
Nothing -> Natural 0
(Just x) -> plusOne $ unfold f x
|
ex4 = map (inf . outf) [Natural 0,Natural 1,Natural 17,Infinity] |
data F a = One | Pair Integer a deriving (Eq,Show) |
pair (Pair a b) = (a,b) |
instance Functor F where
fmap f One = One
fmap f (Pair a b) = Pair a (f b)
|
instance Algebra F [Integer] where
fin One = []
fin (Pair a b) = a:b
|
instance Initial F [Integer] where
-- unpack f to be in a suitable form for foldr
fold f = foldr (cons f) (f One) where
cons f a b = f $ Pair a b
|
ex5 = fin $ fout [1::Integer,2,3,4,5] |
unfoldr p f g x = if p x then []
else f x : unfoldr p f g (g x)
|
ex6 = unfoldr (>20) id (2*) 1 |
instance Coalgebra F [Integer] where
outf [] = One
outf (a:b) = Pair a b
|
instance Final F [Integer] where
-- unpack f to be in a suitable form for unfoldr
unfold f = unfoldr (isOne . f) (fst . pair . f) (snd . pair . f) where
isOne One = True
isOne _ = False
|
ex7 = inf $ outf [1::Integer,2,3,4,5] |
data G a = One' | Triple Integer a a deriving (Show) |
instance Functor G where
fmap f One' = One'
fmap f (Triple a b b') = Triple a (f b) (f b')
|
data Tree a = Empty | Tree a (Tree a) (Tree a) deriving (Show) |
instance Algebra G (Tree Integer) where
fin One' = Empty
fin (Triple a b b') = Tree a b b'
|
instance Initial G (Tree Integer) where
fold f Empty = f One'
fold f (Tree a b b') = f (Triple a (fold f b) (fold f b'))
|
ex8 = fin $ fout $ Tree (6::Integer) (Tree 2 Empty Empty) (Tree 7 Empty (Tree 0 Empty Empty)) |
data H x = H (Char -> Maybe x)
instance Functor H where
fmap f (H g) = H (fmap f . g)
|
unH (H x) = x |
f :: Integer -> Char -> Maybe Integer f 0 'c' = Just 1 f 0 _ = Just 0 |
f 1 'a' = Just 2 f 1 _ = Just 0 |
f 2 't' = Nothing f 2 _ = Just 0 |
runMachine f state "" = False
runMachine f state (c:cs) = case f state c of
Nothing -> True
(Just state') -> runMachine f state' cs
|
ex9 = map (runMachine f 0) ["cat","dog","wildcats"] |
data Hypertree x = HTree (x -> Maybe (Hypertree x)) |
instance Coalgebra H (Hypertree Char) where
outf (HTree f) = H f
|
instance Final H (Hypertree Char) where
unfold f x = HTree (\c -> case unH (f x) c of
Nothing -> Nothing
Just n -> Just (unfold f n)
)
|
run :: Hypertree Char -> [Char] -> Bool |
run _ "" = False
run (HTree f) (c:cs) = case f c of
Nothing -> True
Just x -> run x cs
|
catDetector = unfold (H . f) 0 :: Hypertree Char |
ex10 = map (run catDetector) ["cat","dog","wildcat"] |
catDetector' = inf $ outf $ catDetector |
ex11 = map (run catDetector') ["cat","dog","wildcat"] |
data Command = Halt | Push Integer | Pop | Add | Swap | Print |
interpret Halt stack = Nothing interpret (Push n) stack = Just (n:stack,"") interpret Pop (_:stack) = Just (stack,"") interpret Add (m:n:stack) = Just ((m+n):stack,"") interpret Swap (m:n:stack) = Just (n:m:stack,"") interpret Print (m:stack) = Just (stack,show m) |
data Interface x = I (Command -> Maybe (x,String)) data Executable = E (Command -> Maybe (Executable,String)) |
instance Functor Interface instance Coalgebra Interface Executable instance Final Interface Executable |
data AnyExample = forall a.Show a => AnyExample a |
instance Show AnyExample where show (AnyExample a) = show a |
ex = [
AnyExample ex0,
AnyExample ex1,
AnyExample ex2,
AnyExample ex3,
AnyExample (take 3 ex4), -- because of that Infinity
AnyExample ex5,
AnyExample ex6,
AnyExample ex7,
AnyExample ex8,
AnyExample ex9,
AnyExample ex10,
AnyExample ex11
]
|