-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMusicGraph.hs
118 lines (80 loc) · 3.18 KB
/
MusicGraph.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
module MusicGraph where
import Util (foundIn, uniq)
import Data.List
-- import Music (Name(..), Accidental(..),
-- Quality(..), Number(..), Ratio(..),
-- sharp, flat, natural, pitch, int, note, relnote,
-- crotchet, minim, semibreve, quaver,
-- AbstractPitch2(..), AbstractInt2(..), AbstractDur2(..),
-- AbstractNote(..), Note)
--
--
-- x = note (pitch A sharp) minim
-- y = note (pitch G flat) quaver
--
-- z = relnote (int Dim Fourth) crotchet
data Graph a = a :~> [Graph a]
instance (Show a, Eq a) => Show (Graph a) where
show g = traverseShow [] g
showNode a = "{" ++ (show a) ++ "}"
joinStrings _ [] = ""
joinStrings _ (s:[]) = s
joinStrings k (s:ss) = s ++ k ++ (joinStrings k ss)
traverseShow :: (Eq a, Show a) => [a] -> Graph (a) -> [Char]
traverseShow seen (a :~> succ) = if a `foundIn` seen
then showNode a
else (showNode a) ++ ":~>[" ++ (joinStrings ", " $ map (traverseShow (a:seen)) succ) ++ "]"
instance Functor Graph where
fmap f (a :~> succ) = (f a) :~> (map (fmap f) succ)
traverse :: (Eq a) => (a -> a -> a) -> a -> [a] -> (Graph a) -> a
traverse f e seen (n :~> succ) = if n `foundIn` seen
then e
else foldl f n $ map (traverse f e (n:seen)) succ
mapNodes f (n :~> s) = let (n' :~> s') = f (n :~> s)
in n' :~> (map (mapNodes f) s')
names :: Eq a => Graph a -> [a]
names g = uniq $ names' [] g
where names' seen (n :~> succ) = if n `foundIn` seen
then []
else n:(concatMap (names' (n:seen)) succ)
nodes :: Eq a => (Graph a) -> [Graph a]
nodes g = nodes' [] g
where nodes' seen (n :~> s) = if n `foundIn` seen
then []
else (n :~> s):(concatMap (nodes' (n:seen)) s)
name (n :~> _) = n
succ (_ :~> s) = s
-- successors :: (Eq a) => [a] -> a -> Graph a -> [a]
-- successors seen x (n :~> s)
-- | n `foundIn` seen = []
-- | x `foundIn` (map node s) = n:(concatMap (successors (n:seen) x) s)
-- | otherwise = concatMap (successors (n:seen) x) s
successors x g = case findNode x g of
Just (n :~> s) -> map name s
Nothing -> []
modifyNode f x = mapNodes (\(n :~> s) -> if n == x then f (n :~> s) else n :~> s)
first _ [] = Nothing
first f (x:xs)
| f x = Just x
| otherwise = first f xs
findNode x g = first (\(n :~> _) -> n == x) (nodes g)
addEdge x y g = case findNode y g of
Just y' -> modifyNode (\(n :~> s) -> n :~> (y':s)) x g
Nothing -> g
-- delEdge x y = modifyNode (\(n :~> s) -> n :~> ()) x
a = 4 :~> [b,d]
b = 5 :~> [c]
c = 6 :~> [f]
d = 1 :~> [e]
e = 2 :~> [f]
f = 3 :~> []
mergeNode g (n' :~> []) = g
mergeNode g (n' :~> (x:xs)) = mergeNode (addEdge n' (name x) g) (n' :~> xs)
mergeGraphs a b = mergeGraphs' a (nodes b) where
mergeGraphs' g [] = g
mergeGraphs' g (h:hs) = mergeGraphs' (mergeNode g h) hs
reverseNode g (n :~> s) = let n' = n :~> []
rev = map (\x -> (name x) :~> [n']) s
in foldr mergeNode g rev
--uniqUnder =
-- transpose (n :~> s) =