\int_{0}^{1}\frac{x^{4}\left(1-x\right)^{4}}{1+x^{2}}dx
=\frac{22}{7}-\pi
You know, I think I won't delete this. It's a celebration of my having embedded some TeX using the advice at Bot Cyborg.
\int_{0}^{1}\frac{x^{4}\left(1-x\right)^{4}}{1+x^{2}}dx
=\frac{22}{7}-\pi
Δf(x,y) = (f(x)-f(y))/(x-y)
Δ(fg)(x,y) = (f(x)g(x)-f(y)g(y))/(x-y)
= (f(x)g(x)-f(x)g(y)+f(x)g(y)-f(y)g(y))/(x-y)
= f(x)Δg(x,y)+g(y)Δf(x,y)
f(x) = 1+x f(x)
Δf(x,y) = x Δf(x,y)+f(y)
Δf(x,y) = (xN-yN)/(x-y) = xN-1+xN-2y+xN-3y2+...+yN-1

right :: p j + (Δp c j , c) → (j , Δp c j ) + p c
ΔT(X,Y) = 1/(1-(T(X)+T(Y))

right, defined above, a massaged version of the definition of finite difference? (Hint: define d=((f(x)-f(y))/(x-y). In this equation, eliminate the division by a suitable multiplication and eliminate the subtraction by a suitable addition. And remember that (,) is Haskell notation for the product of types.)
> {-# LANGUAGE NoMonomorphismRestriction,GeneralizedNewtypeDeriving #-}
> import Control.Arrow
> import Control.Monad
> import Control.Monad.Instances
> import Control.Monad.State
> import Data.Either
> import Data.Function
> import Random
> import qualified Data.List as L
> import qualified Data.Map as M

> data Search c a = Leaf { lb::c, leaf::a}
> | Choice { lb::c, choices::[Search c a] } deriving Show
> ex1 = Choice 0 [
> Choice (-log 0.1) [
> Leaf (-log 0.5) 'A',
> Leaf (-log 0.5) 'B'],
> Choice (-log 0.2) [
> Leaf (-log 0.6) 'C',
> Leaf (-log 0.4) 'D']]
> instance Functor (Search c) where
> fmap f (Leaf c a ) = Leaf c $ f a
> fmap f (Choice c as) = Choice c $ map (fmap f) as
> instance Num c => Monad (Search c) where
> return = Leaf 0
> a >>= f = join $ fmap f a where
> join (Leaf c a ) = Choice c [a]
> join (Choice c as) = Choice c $ map join as
> instance Num c => MonadPlus (Search c) where
> mzero = Choice 0 []
> a `mplus` b = Choice 0 [a,b]
> data Ord a => Tree a = Null | Fork a (Tree a) (Tree a) deriving Show
> isEmpty :: Ord a => Tree a -> Bool
> isEmpty Null = True
> isEmpty (Fork x a b) = False
> minElem :: Ord a => Tree a -> a
> minElem (Fork x a b) = x
> deleteMin :: Ord a => Tree a -> Tree a
> deleteMin (Fork x a b) = merge a b
> insert :: Ord a => a -> Tree a -> Tree a
> insert x a = merge (Fork x Null Null) a
> merge :: Ord a => Tree a -> Tree a -> Tree a
> merge a Null = a
> merge Null b = b
> merge a b
> | minElem a <= minElem b = connect a b
> | otherwise = connect b a
> connect (Fork x a b) c = Fork x b (merge a c)
> instance (Num c) => Eq (Search c a) where
> (==) = (==) `on` lb
> instance (Num c,Ord c) => Ord (Search c a) where
> compare = compare `on` lb
> bumpUp delta (Leaf c a) = Leaf (delta+c) a
> bumpUp delta (Choice c as) = Choice (delta+c) as
> runSearch :: (Num c,Ord c) => Tree (Search c a) -> [Either c a]
> runSearch Null = []
> runSearch queue = let
> m = minElem queue
> queue' = deleteMin queue
> in case m of
> Leaf c a -> Left c : Right a : runSearch queue'
> Choice c as -> Left c : (runSearch $ foldl (flip insert) queue' $ map (bumpUp c) as)
> integers m = Choice 1 [Leaf 0 m,integers (m+1)]
> test = do
> a <- integers 1
> b <- integers 1
> c <- integers 1
> guard $ a*a+b*b==c*c
> return (a,b,c)
> test1 = runSearch (insert test Null)
> reduce [] = []
> reduce (Left a : Left b : bs) = reduce (Left b : bs)
> reduce (Left a : bs) = Left (exp (-a)) : reduce bs
> reduce (Right a : bs) = Right a : reduce bs
> test2 = reduce test1
> data Noun = Noun String deriving (Show,Eq,Ord)
> data Verb = Verb String deriving (Show,Eq,Ord)
> data Adj = Adj String deriving (Show,Eq,Ord)
> data Prep = Prep String deriving (Show,Eq,Ord)
> data NP = NP [Adj] Noun deriving (Show,Eq,Ord)
> data PP = PP Prep Noun deriving (Show,Eq,Ord)
> data Sentence = Sentence [NP] Verb [NP] [PP] deriving (Show,Eq,Ord)
> class UnParse a where
> unParse :: a -> String
> instance UnParse Noun where
> unParse (Noun a) = a
> instance UnParse Verb where
> unParse (Verb a) = a
> instance UnParse Adj where
> unParse (Adj a) = a
> instance UnParse Prep where
> unParse (Prep a) = a
> instance UnParse NP where
> unParse (NP a b) = concatMap unParse a ++ unParse b
> instance UnParse PP where
> unParse (PP a b) = unParse a ++ unParse b
> instance UnParse Sentence where
> unParse (Sentence a b c d) = concatMap unParse a ++ unParse b ++ concatMap unParse c ++ concatMap unParse d
> class Transducer t where
> char :: Char -> t Char
> choose :: [(Float,t a)] -> t a
> string :: (Monad t, Transducer t) => [Char] -> t [Char]
> string "" = return ""
> string (c:cs) = do {char c; string cs; return (c:cs)}
> noun :: (Monad t, Transducer t) => t Noun
> noun = do
> a <- choose [(0.5,string "ab"),(0.5,string "ba")]
> return $ Noun a
> verb :: (Monad t, Transducer t) => t Verb
> verb = do
> a <- choose [(0.5,string "aa"),(0.5,string "b")]
> return $ Verb a
> adjective :: (Monad t, Transducer t) => t Adj
> adjective = do
> a <- choose [(0.5,string "ab"),(0.5,string "aa")]
> return $ Adj a
> parsePrep = do
> a <- choose [(0.5,string "a"),(0.5,string "b")]
> return $ Prep a
> many :: (Monad t, Transducer t) => Float -> t a -> t [a]
> many p t = choose [
> (p,return []),
> (1-p,do
> a <- t
> as <- many p t
> return $ a:as)]
> many1 p t = do
> a <- t
> as <- many p t
> return (a:as)
> parseNP = do
> a <- many 0.5 adjective
> b <- noun
> return $ NP a b
> parsePP = do
> a <- parsePrep
> b <- noun
> return $ PP a b
> sentence = do
> a <- many 0.5 parseNP
> b <- verb
> c <- many 0.5 parseNP
> d <- many 0.5 parsePP
> return $ Sentence a b c d
> newtype Generator a = Generator { unGen :: State StdGen a } deriving Monad
> newtype Parser a = Parser { runParse :: (String -> Search Float (a,String)) }
> instance Transducer Generator where
> char a = return a
> choose p = do
> r <- Generator (State random)
> case (L.find ((>=r) . fst) $ zip (scanl1 (+) (map fst p)) (map snd p)) of
> Just opt -> snd opt
> gen = mkStdGen 12343210
> generate n partOfSpeech = (unGen $ sequence (replicate n partOfSpeech)) `evalState` gen
> test3 = mapM_ print $ generate 10 sentence
> generateAndTest n partOfSpeech chars = do
> a <- generate n sentence
> guard $ unParse a == chars
> return a
> collectResults n partOfSpeech chars = M.fromListWith (+) $ map (flip (,) 1) $
> generateAndTest n partOfSpeech chars
> countResults n partOfSpeech chars = mapM_ print $ L.sortBy (flip compare `on` snd) $
> M.toList $ collectResults n partOfSpeech chars
> test4 = countResults 100000 (noun :: Parser Noun) "abab"
> instance Monad Parser where
> return a = Parser (\cs -> return (a,cs))
> p >>= f = Parser (\cs -> do
> (a,cs') <- runParse p cs
> runParse (f a) cs')
> instance MonadPlus Parser where
> mzero = Parser (\cs -> mzero)
> p `mplus` q = Parser (\cs -> runParse p cs `mplus` runParse q cs)
> instance Transducer Parser where
> char c = Parser $ char' where
> char' "" = mzero
> char' (a:as) = if a==c then return (a,as) else mzero
> choose p = foldl1 mplus $ map (\(p,x) -> prob p >> x) p where
> prob p = Parser (\cs -> Leaf (-log p) ((),cs))
> goParse (Parser f) x = runSearch $ insert (f x) Null
> end = Parser (\cs -> if cs=="" then return ((),"") else mzero)
> withEnd g = do
> a <- g
> end
> return a
> normalise results = let total = last (lefts results)
> in map (\x -> case x of
> Left a -> a / total
> Right b -> b
> ) results
> findParse chars = mapM_ print $ reduce $ runSearch $
> insert (runParse (withEnd sentence) chars) Null
> main = do
> let string = "ababbbab"
> findParse string
> print "-------------------"
> countResults 1000000 (sentence :: Parser Sentence) string
> import Data.Char
> import Control.Monad
> import Data.Monoid
> import Data.List
> data PList a = P { unO :: [[a]] } deriving (Show,Eq)
> instance Functor PList where
> fmap f (P xs) = P (fmap (fmap f) xs)
> headm :: Monoid m => [m] -> m
> headm (a:as) = a
> headm [] = mempty
> tailm :: Monoid m => [m] -> [m]
> tailm (a:as) = as
> tailm [] = []
> zipm :: Monoid m => [[m]] -> [m]
> zipm ms | all null ms = []
> zipm ms = let
> heads = map headm ms
> tails = map tailm ms
> h = mconcat heads
> t = zipm (filter (not . null) tails)
> in h : t
> instance Monad PList where
> return x = P [[x]]
> x >>= f = let P xs = (fmap (unO . f) x) in P (join xs) where
> join [] = []
> join (m:ms) = let
> part1 = zipm m
> part2 = join ms
> in headm part1 : zipm [tailm part1,part2]

> instance MonadPlus PList where
> mzero = P []
> mplus (P xs) (P ys) = P (zipm [xs,ys])
> ex1 = do
> x <- P $ map (\x -> [x]) [1..]
> y <- P $ map (\y -> [y]) [1..]
> z <- P $ map (\z -> [z]) [1..]
> guard $ x*x+y*y==z*z
> return $ (x,y,z)
> penalty :: PList ()
> penalty = P [[],[()]]
> newtype Parser a = Parser (String -> PList (a,String))
> parse (Parser f) x = f x
> instance Monad Parser where
> return a = Parser (\cs -> P [[(a,cs)]])
> p >>= f = Parser (\cs -> do
> (a,cs') <- parse p cs
> parse (f a) cs')
> instance MonadPlus Parser where
> mzero = Parser (\cs -> mzero)
> p `mplus` q = Parser (\cs -> parse p cs `mplus` parse q cs)
> item :: Parser Char
> item = Parser (\cs -> case cs of
> "" -> mzero
> (c:cs) -> P [[(c,cs)]])
> sat :: (Char -> Bool) -> Parser Char
> sat p = do
> c <- item
> if p c then return c else mzero
> char :: Char -> Parser Char
> char c = sat (c ==)
> lowers = "1234567890-=/"
> uppers = "!@#$%^&*()_+?"
> lower x = lookup x (zip uppers lowers)
> upper x = lookup x (zip lowers uppers)
> upperChar x = case upper x of
> Nothing -> mzero
> Just y -> char y >> return x
> lowerChar x = case lower x of
> Nothing -> mzero
> Just y -> char y >> return x
> avoid :: Parser ()
> avoid = Parser $ \cs -> do
> penalty
> return ((),cs)
> keyChar x = char x `mplus` (avoid >> upperChar x) `mplus` (avoid >> lowerChar x)
> digit = do
> x <- foldl mplus mzero (map keyChar "0123456789")
> return (fromIntegral (ord x-ord '0'))
> number1 :: Integer -> Parser Integer
> number1 m = return m `mplus` do
> n <- digit
> number1 (10*m+n)
> number :: Parser Integer
> number = do
> n <- digit
> number1 n
> chainl :: Parser a -> Parser (a -> a -> a) -> a -> Parser a
> chainl p op a = (p `chainl1` op) `mplus` return a
> chainl1 :: Parser a -> Parser (a -> a -> a) -> Parser a
> p `chainl1` op = do {a <- p; rest a}
> where
> rest a = (do
> f <- op
> b <- p
> rest (f a b)) `mplus` return a
> shouldHave c = keyChar c `mplus` (avoid >> return c)
> expr = term `chainl1` addop
> term = monomial `chainl1` mulop
> monomial = factor `chainl1` powop
> factor = number `mplus` do {shouldHave '('; n <- expr; shouldHave ')'; return n}
> powop = keyChar '^' >> return (^)
> addop = do {keyChar '+'; return (+)} `mplus` do {keyChar '-'; return (-)}
> mulop = do {keyChar '*'; return (*)} `mplus` do {keyChar '/'; return (div)}
> end :: Parser ()
> end = Parser $ \cs ->
> if null cs then P [[((),"")]] else mzero
> completeExpr = do
> n <- expr
> end
> return n
> ex2 = parse completeExpr "2^(1+3"
PList is a variation of the convolution monad I described here. It deals with the "wrong category" aspect so it is a true Haskell monad. Penalty lists form some kind of dual to the convolution comonad.join example more complex so it's easier to generalise from it.




> {-# LANGUAGE MultiParamTypeClasses,FlexibleInstances,FunctionalDependencies,GeneralizedNewtypeDeriving #-}
> module Main where
> import Data.HashTable
> import Data.List as L
> import Data.Int
> import Data.Array
> import GHC.Arr
> import qualified Data.Map as M
> import Control.Monad
> infixl 5 .+
> infixl 6 .*
> data I = A | B | C | D deriving (Eq,Ord,Show,Ix,Enum)
> c' (a,b,c,d) = hashString ("C" ++ show (a,b,c,d))
Memoisable type class with a memo method. So I'll be using c instead of c':symmetrise function. The idea is that the 4 bonds coming out from (singly-bonded) carbon can be thought of as lying at the corners of a tetrahedron.
c (i,j,k,l) == c (j,i,l,k). We can enforce this by summing over all 24 permutations of the arguments compatible with this symmetry, also known as A4. So a4 lists all of these permutations:
> a4 (i,j,k,l) = [
> (i,j,k,l),
> (j,i,l,k),
> (k,l,i,j),
> (l,k,j,i),
> (i,k,l,j),
> (i,l,j,k),
> (k,j,l,i),
> (l,j,i,k),
> (j,l,k,i),
> (l,i,k,j),
> (j,k,i,l),
> (k,i,j,l)
> ]
symmetrise performs the summation:
> symmetrise group f x = sum (map f (group x))
> h = memo $ \a -> hashString ("H" ++ show a) .* return ()
> s2 (i,j) = [ (i,j), (j,i) ]
> o' (a,b) = hashString ("O" ++ show (a,b))
> o = memo $ \x -> symmetrise s2 o' x .* return ()
> bond :: V Int32 I
> bond = return A .+ return B .+ return C .+ return D
> h2 = simp $ do
> i <- bond
> h ! i
> h ! i
i <- bond makes i a bond which we then attach to two hydrogen atoms. Evaluating h2 will give us the hash for hydrogen gas.
> h_ :: V Int32 I
> h_ = do
> m <- bond
> h ! m
> return m
ch2_ accepts one bond and returns another. Once memoised it is, in effect, just a 4x4 matrix and can be used to rapidly build chains.
> ch2_ = memo $ \i -> simp $ do
> k <- bond
> l <- bond
> m <- bond
> h ! l
> h ! m
> c ! (i,k,l,m)
> return k
> alkyl_ 0 = h_
> alkyl_ n = simp $ do
> i <- alkyl_ (n-1)
> ch2_ ! i
> alkane n = simp $ alkyl_ n >>= (h ! )
> methane = alkane 1
> oh = memo $ \i -> simp $ do
> j <- bond
> h ! j
> o ! (i,j)
> ethanol = simp $ do
> i <- alkyl_ 2
> oh ! i
> doubleBond :: V Int32 (I,I)
> doubleBond = simp $ do
> i <- bond
> j <- bond
> return (i,j)
symmetrise if we wanted twistable bonds.
> c_c = memo $ \(i,j,k,l) -> simp $ do
> (m,n) <- doubleBond
> c ! (i,j,m,n)
> c ! (m,n,k,l)
> ethene = simp $ do
> i <- h_
> j <- h_
> k <- h_
> l <- h_
> c_c ! (i,j,k,l)
> ch3_ = simp $ do
> l <- h_
> ch2_ ! l
> propene = simp $ do
> j <- ch3_
> i <- h_
> k <- h_
> l <- h_
> c_c ! (i,j,k,l)
> cisbut2ene = simp $ do
> i <- ch3_
> j <- h_
> k <- ch3_
> l <- h_
> c_c ! (i,j,k,l)
> transbut2ene = simp $ do
> i <- h_
> j <- ch3_
> k <- ch3_
> l <- h_
> c_c ! (i,j,k,l)
> cisbut2ene' = simp $ do
> i <- h_
> j <- ch3_
> k <- h_
> l <- ch3_
> c_c ! (i,j,k,l)
> _2methylpropene = simp $ do
> i <- ch3_
> j <- ch3_
> k <- h_
> l <- h_
> c_c ! (i,j,k,l)
> _2methylpropene' = simp $ do
> i <- h_
> j <- h_
> k <- ch3_
> l <- ch3_
> c_c ! (i,j,k,l)
> ring1 (p,q,r,s,t,u) = simp $ do
> i <- bond
> j <- bond
> k <- bond
> c_c ! (j,q,i,p)
> c_c ! (i,u,k,t)
> c_c ! (k,s,j,r)

> ring = memo $ \(p,q,r,s,t,u) -> simp $ ring1 (p,q,r,s,t,u) .+ ring1 (q,r,s,t,u,p)
> phenyl = memo $ \p -> simp $ do
> q <- h_
> r <- h_
> s <- h_
> t <- h_
> u <- h_
> ring ! (p,q,r,s,t,u)
> benzene :: V Int32 ()
> benzene = simp $ do
> i <- bond
> phenyl ! i
> h ! i
> phenol :: V Int32 ()
> phenol = simp $ do
> i <- bond
> phenyl ! i
> oh ! i
> toluene :: V Int32 ()
> toluene = simp $ do
> i <- ch3_
> phenyl ! i
> toluene' :: V Int32 ()
> toluene' = simp $ do
> p <- h_
> q <- h_
> r <- h_
> s <- ch3_
> t <- h_
> u <- h_
> ring ! (p,q,r,s,t,u)
> toluene'' :: V Int32 ()
> toluene'' = simp $ do
> p <- h_
> q <- h_
> r <- ch3_
> s <- h_
> t <- h_
> u <- h_
> ring ! (p,q,r,s,t,u)
> _1_2_dimethylbenzene = simp $ do
> p <- ch3_
> q <- ch3_
> r <- h_
> s <- h_
> t <- h_
> u <- h_
> ring ! (p,q,r,s,t,u)
> _1_3_dimethylbenzene = simp $ do
> p <- ch3_
> q <- h_
> r <- ch3_
> s <- h_
> t <- h_
> u <- h_
> ring ! (p,q,r,s,t,u)
> _1_4_dimethylbenzene = simp $ do
> p <- ch3_
> q <- h_
> r <- h_
> s <- ch3_
> t <- h_
> u <- h_
> ring ! (p,q,r,s,t,u)
> _1_5_dimethylbenzene = simp $ do
> p <- ch3_
> q <- h_
> r <- h_
> s <- h_
> t <- ch3_
> u <- h_
> ring ! (p,q,r,s,t,u)
> main = do
> print $ "toluene = " ++ show toluene
> print $ "toluene' = " ++ show toluene'
> print $ "toluene'' = " ++ show toluene''
> print $ "_1_2_dimethylbenzene = " ++ show _1_2_dimethylbenzene
> print $ "_1_3_dimethylbenzene = " ++ show _1_3_dimethylbenzene
> print $ "_1_4_dimethylbenzene = " ++ show _1_4_dimethylbenzene
> print $ "_1_5_dimethylbenzene = " ++ show _1_5_dimethylbenzene
> class Memoisable ix where
> memo :: (ix -> a) -> Array ix a
> instance Memoisable I where
> memo f = array (A,D) [(i,f i) | i <- [A .. D]]
> instance Memoisable (I,I) where
> memo f = array ((A,A),(D,D)) [(i,f i) |
> p <- [A .. D],
> q <- [A .. D],
> let i = (p,q) ]
> instance Memoisable (I,I,I,I) where
> memo f = array ((A,A,A,A),(D,D,D,D)) [(i,f i) |
> p <- [A .. D],
> q <- [A .. D],
> r <- [A .. D],
> s <- [A .. D],
> let i = (p,q,r,s) ]
> instance Memoisable (I,I,I,I,I,I) where
> memo f = array ((A,A,A,A,A,A),(D,D,D,D,D,D)) [(i,f i) |
> p <- [A .. D],
> q <- [A .. D],
> r <- [A .. D],
> s <- [A .. D],
> t <- [A .. D],
> u <- [A .. D],
> let i = (p,q,r,s,t,u) ]
Data.Array:
> instance (Ix a1, Ix a2, Ix a3, Ix a4, Ix a5, Ix a6) => Ix (a1,a2,a3,a4,a5,a6) where
> range ((l1,l2,l3,l4,l5,l6),(u1,u2,u3,u4,u5,u6)) =
> [(i1,i2,i3,i4,i5,i6) | i1 <- range (l1,u1),
> i2 <- range (l2,u2),
> i3 <- range (l3,u3),
> i4 <- range (l4,u4),
> i5 <- range (l5,u5),
> i6 <- range (l6,u6)]
> unsafeIndex ((l1,l2,l3,l4,l5,l6),(u1,u2,u3,u4,u5,u6)) (i1,i2,i3,i4,i5,i6) =
> unsafeIndex (l6,u6) i6 + unsafeRangeSize (l6,u6) * (
> unsafeIndex (l5,u5) i5 + unsafeRangeSize (l5,u5) * (
> unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
> unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
> unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
> unsafeIndex (l1,u1) i1)))))
> inRange ((l1,l2,l3,l4,l5,l6),(u1,u2,u3,u4,u5,u6)) (i1,i2,i3,i4,i5,i6) =
> inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
> inRange (l3,u3) i3 && inRange (l4,u4) i4 &&
> inRange (l5,u5) i5 && inRange (l6,u6) i6
Int32 isn't a field.
> swap (x,y) = (y,x)
> class Num k => VectorSpace k v | v -> k where
> zero :: v
> (.+) :: v -> v -> v
> (.*) :: k -> v -> v
> (.-) :: v -> v -> v
> v1 .- v2 = v1 .+ ((-1).*v2)
> data V k a = V { unV :: [(k,a)] } deriving (Show)
> reduce x = filter ((/=0) . fst) $ fmap swap $ M.toList $ M.fromListWith (+) $ fmap swap $ x
> simp (V x) = V (reduce x)
> instance (Ord a,Num k) => Eq (V k a) where
> V x==V y = reduce x==reduce y
> instance (Ord a,Num k,Ord k) => Ord (V k a) where
> compare (V x) (V y) = compare (reduce x) (reduce y)
> instance Num k => Functor (V k) where
> fmap f (V as) = V $ map (\(k,a) -> (k,f a)) as
> instance Num k => Monad (V k) where
> return a = V [(1,a)]
> x >>= f = join (fmap f x)
> where join x = V $ concat $ fmap (uncurry scale) $ unV $ fmap unV x
> scale k1 as = map (\(k2,a) -> (k1*k2,a)) as
> instance Num r => MonadPlus (V r) where
> mzero = V []
> mplus (V x) (V y) = V (x++y)
> instance (Num k,Ord a) => VectorSpace k (V k a) where
> zero = V []
> V x .+ V y = V (x ++ y)
> (.*) k = (>>= (\a -> V [(k,a)]))
> e = return :: Num k => a -> V k a
> coefficient b (V bs) = maybe 0 id (L.lookup b (map swap (reduce bs)))
> {-# LANGUAGE MultiParamTypeClasses,FunctionalDependencies,FlexibleInstances #-}
> module Main where
> import qualified Data.Map as M
> import Control.Monad
> infixl 5 .+
> infixl 6 .*
> data Space = X | Y | Z deriving (Eq,Show,Ord)

V Float Space, for example:
> u,v,w :: V Float Space
> u = return X .- return Y
> v = return X .+ 2.* return Y
> w = return Y .- return Z
() -> V Float Space instead.

> cup :: (Space,Space) -> V Float ()
> cup (i,j) = case (i,j) of
> (X,X) -> return ()
> (Y,Y) -> return ()
> (Z,Z) -> return ()
> otherwise -> 0 .* return ()
> vdotw = do
> i <- v
> j <- w
> cup (i,j)

In other words, turning a vector v upside down turns it into a dual vector that takes w to the dot product of v and w. Here's some code for making the dual of v.
> dual :: V Float Space -> Space -> V Float ()
> dual v i = do
> j <- v
> cup (i,j)

> cross :: (Space,Space) -> V Float Space
> cross (X,Y) = return Z
> cross (Y,Z) = return X
> cross (Z,X) = return Y
> cross (Y,X) = (-1) .* return Z
> cross (Z,Y) = (-1) .* return X
> cross (X,Z) = (-1) .* return Y
> cross _ = mzero


> trident :: (Space,Space,Space) -> V Float ()
> trident (i,j,k) = do
> l <- cross (i,j)
> cup (l,k)

> cap :: () -> V Float (Space,Space)
> cap () = return (X,X) .+ return (Y,Y) .+ return (Z,Z)

> cupcap i = do
> (j,k) <- cap ()
> cup (i,j)
> return k
cupcap to X, Y and Z you'll see it has exactly the same effect as return, which does indeed represent the identity.cup and cap were implemented it would be impossible for k to be a copy of i. If you follow the flow of information through that code then i disappears into cup and k is read from cap without it seeing i. If we read from top to bottom we can think of cap as emitting a pair of objects and of cup as absorbing two. There is no way that any information about i can be communicated to k. But in the vector space monad, k can depend on i. As I've mentioned a few times over the years, the universe is described by quantum mechanics which can be described using the vector space monad. Amazingly the above piece of code, or at least something like it, can be physically realised in terms of particles. It describes a process that is fundamentally quantum, and not classical. In fact, Coecke shows that this is a precursor to quantum teleportation in section 3c of this paper. You could also think in terms of information about i being sent back in time through the cap. That's the idea behind this paper on Effective Quantum Time Travel.)
> fork () = do
> (i,j) <- cap ()
> (k,l) <- cap ()
> m <- cross (j,k)
> return (i,l,m)

> a :: Space -> V Float Space
> a X = 2 .* return X
> a Y = return Z
> a Z = (-1) .* return Y

> b :: Space -> V Float Space
> b l = do
> (i,j) <- cap ()
> k <- a j
> cup (k,l)
> return i

> det a = do
> (i,j,k) <- fork ()
> i' <- a i
> j' <- a j
> k' <- a k
> (1/6.0) .* trident (i',j',k')
> swap (x,y) = (y,x)
> class Num k => VectorSpace k v | v -> k where
> zero :: v
> (.+) :: v -> v -> v
> (.*) :: k -> v -> v
> (.-) :: v -> v -> v
> v1 .- v2 = v1 .+ ((-1).*v2)
> data V k a = V { unV :: [(k,a)] }
> instance (Num k,Ord a,Show a) => Show (V k a) where
> show (V x) = show (reduce x)
> reduce x = filter ((/=0) . fst) $ fmap swap $ M.toList $ M.fromListWith (+) $ fmap swap $ x
> instance (Ord a,Num k) => Eq (V k a) where
> V x==V y = reduce x==reduce y
> instance (Ord a,Num k,Ord k) => Ord (V k a) where
> compare (V x) (V y) = compare (reduce x) (reduce y)
> instance Num k => Functor (V k) where
> fmap f (V as) = V $ map (\(k,a) -> (k,f a)) as
> instance Num k => Monad (V k) where
> return a = V [(1,a)]
> x >>= f = join (fmap f x)
> where join x = V $ concat $ fmap (uncurry scale) $ unV $ fmap unV x
> scale k1 as = map (\(k2,a) -> (k1*k2,a)) as
> instance Num r => MonadPlus (V r) where
> mzero = V []
> mplus (V x) (V y) = V (x++y)
> instance (Num k,Ord a) => VectorSpace k (V k a) where
> zero = V []
> V x .+ V y = V (x ++ y)
> (.*) k = (>>= (\a -> V [(k,a)]))
> e = return :: Num k => a -> V k a
> coefficient b (V bs) = maybe 0 id (lookup b (map swap (reduce bs)))







I wanted to address some of the comments so I've added an appendix where I use the Haskell type checker to tighten up the statements I make above. There are some places I made some choices and I decided to make the specialiser output machines rather than pictures. This code doesn't actually do anything.
One important thing to note is that with these definitions the first projection is a function describing the action of a machine after it has been given one input. The second and third projections are dedicated machines.
> module Futamura whereI'm using P a to represent the type of a Picture (or Plan, or Program) of how to perform an operation of type a and M a to represent a Machine (or executable) that executes such an operation.
I use M because I want to make explicit what is actually a machine. In Haskell a type a -> b -> c can be thought of as a machine that takes an input of type a and an input of type b and outputs a c, or as a machine that takes as input an a and outputs another machine that makes a c from a b. I distinguish those by using M (a -> b -> c) for the former and M (a -> M (b -> c)) for the latter.
I'm not actually going to built a Futamura specialiser so the right hand sides hare are just filler:
> data P a = P > data M a = MRunning a machine gives a way to perform what the machine is designed to do. We're not really running machines in Haskell so we have an undefined right hand side.
> run :: M a -> a > run = undefinedA specialiser is a machine that takes as first input a picture of a process mapping an a and a b to a c. It also takes as argument the specialised value for the input for the process. It then outputs a dedicated machine for the specialised process:
> specialise :: M (P (a -> b -> c) -> a -> M (b -> c)) > specialise = undefinedWe actually need the picture of the specialiser as it's going to be specialised:
> specialisePicture :: P (P (a -> b -> c) -> a -> M (b -> c)) > specialisePicture = undefinedFor the first projection we'll need an interpreter. An interpreter is a general purpose machine that takes pictures of how to map an a to a b, as well as an actual a, and can then give you a b:
> interpreter :: M (P (a -> b) -> a -> b) > interpreter = undefinedAnd what we really need is a picture of an interpreter:
> interpreterPicture :: P (P (a -> b) -> a -> b) > interpreterPicture = undefinedThe first projection turns a picture into a dedicated machine. So it functions as a compiler. But note that it's not itself a dedicated machine. It's a general purpose machine which acts as a compiler when given (a picture of) an interpreter as first input:
> proj1 :: P (input -> output) -> M (input -> output) > proj1 = run specialise interpreterPictureThe second projection is a dedicated machine that does the task of proj1. So it's a compiler:
> proj2 :: M (P (input -> output) -> M (input -> output)) > proj2 = run specialise specialisePicture interpreterPictureAn interpreter is something that can take a computer program and some input and generate the output you expect from the program. A compiler, on the other hand, converts programs into dedicated machines to process the input into the output. And that's exactly what the third projection does:
> proj3 :: M (P (program -> input -> output) -> M (program -> M (input -> output))) > proj3 = run specialise specialisePicture specialisePicture