```module Haskore.Example.Fractal where

import Prelude hiding (init)
import System.Random (randomRs, mkStdGen)
import Data.Array (Array, (!), listArray, bounds)

type Vector a = [a]
type Matrix a = [Vector a]
type AT     a = Vector a -> Vector a
type IFS    a = Array Int (AT a)

-- First define some general matrix operations.
-- These will facilitate moving to higher dimensions later.

vadd :: Num a => Vector a -> Vector a -> Vector a

vvmult :: Num a => Vector a -> Vector a -> a
vvmult v1 v2 = sum (zipWith (*) v1 v2)

mvmult :: Num a => Matrix a -> Vector a -> Vector a
mvmult m v = map (vvmult v) m

cvmult :: Num a => a -> Vector a -> Vector a
cvmult z = map (z*)

---------------------------------------------------------------------

{- The following simulates the Iterated Function System for the
Sierpinski Triangle as described in Barnsley's "Desktop Fractal
Design Handbook". -}

-- First the affine transformations:

w0, w1, w2 :: Fractional a => AT a
w0 v = (cvmult 0.01 ([[50,0],[0,50],[50,0]] `mvmult` v))
w1 v = (cvmult 0.01 ([[50,0],[0,50],[50,0]] `mvmult` v))
w2 v = (cvmult 0.01 ([[50,0],[0,50],[50,0]] `mvmult` v))

init0 :: Num a => Vector a
init0 = [0,0,0]

-- Now we have an Iterated Function System:

ws :: Fractional a => IFS a
ws = let wl = [w0,w1,w2]
in  listArray (0, length wl - 1) wl

-- And here is the result:

result :: [Vector Rational]
result =
let ws' = ws -- make it monomorph
f init r = (ws'!r) init
in  scanl f init0 (randomRs (bounds ws') (mkStdGen 215))

-- where "randomRs" computes a list of random indices in the range 0-2,
-- which simulates flipping the coin in Barnsley.

--------

mkNote :: [Rational] -> Melody.T ()
mkNote [a,b,c] =
Music.rest (Dur.fromRatio (b/20)) +:+
Melody.note (Pitch.fromInt (round a)) (Dur.fromRatio (c/20)) ()
mkNote _ = error "mkNote: Need three components."

{- Of course, a triple would be the better type
but that would complicate the vector computation. -}

sourceToMusic :: [[Rational]] -> Melody.T ()
sourceToMusic s = Music.chord (map mkNote s)

song :: Melody.T ()
song = Music.transpose (-12) (sourceToMusic (take 128 result))
```