Skip to content

Commit 7ed840c

Browse files
committed
Cabal-syntax: trade TypeFamilies for FunctionalDependencies
The overarching goal is to make Cabal-syntax compilable by MicroHs, which does not support TypeFamilies, but does support FunctionalDependencies.
1 parent f26cbdc commit 7ed840c

File tree

5 files changed

+51
-55
lines changed

5 files changed

+51
-55
lines changed

Cabal-syntax/Cabal-syntax.cabal

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ library
226226
ScopedTypeVariables
227227
StandaloneDeriving
228228
Trustworthy
229-
TypeFamilies
230229
TypeOperators
231230
TypeSynonymInstances
232231
UndecidableInstances

Cabal-syntax/src/Distribution/Compat/Graph.hs

Lines changed: 48 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
{-# LANGUAGE BangPatterns #-}
22
{-# LANGUAGE FlexibleContexts #-}
3+
{-# LANGUAGE FlexibleInstances #-}
4+
{-# LANGUAGE FunctionalDependencies #-}
5+
{-# LANGUAGE MultiParamTypeClasses #-}
36
{-# LANGUAGE ScopedTypeVariables #-}
4-
{-# LANGUAGE TypeFamilies #-}
57
{-# LANGUAGE TypeOperators #-}
68
{-# LANGUAGE UndecidableInstances #-}
79

@@ -107,40 +109,40 @@ import qualified Distribution.Compat.Prelude as Prelude
107109

108110
-- | A graph of nodes @a@. The nodes are expected to have instance
109111
-- of class 'IsNode'.
110-
data Graph a = Graph
111-
{ graphMap :: !(Map (Key a) a)
112+
data Graph keyA a= Graph
113+
{ graphMap :: !(Map keyA a)
112114
, -- Lazily cached graph representation
113115
graphForward :: G.Graph
114116
, graphAdjoint :: G.Graph
115117
, graphVertexToNode :: G.Vertex -> a
116-
, graphKeyToVertex :: Key a -> Maybe G.Vertex
117-
, graphBroken :: [(a, [Key a])]
118+
, graphKeyToVertex :: keyA -> Maybe G.Vertex
119+
, graphBroken :: [(a, [keyA])]
118120
}
119121

120122
-- NB: Not a Functor! (or Traversable), because you need
121-
-- to restrict Key a ~ Key b. We provide our own mapping
123+
-- to restrict keyA ~ Key b. We provide our own mapping
122124
-- functions.
123125

124126
-- General strategy is most operations are deferred to the
125127
-- Map representation.
126128

127-
instance Show a => Show (Graph a) where
129+
instance Show a => Show (Graph keyA a) where
128130
show = show . toList
129131

130-
instance (IsNode a, Read a, Show (Key a)) => Read (Graph a) where
132+
instance (IsNode keyA a, Read a, Show keyA) => Read (Graph keyA a) where
131133
readsPrec d s = map (first fromDistinctList) (readsPrec d s)
132134

133-
instance (IsNode a, Binary a, Show (Key a)) => Binary (Graph a) where
135+
instance (IsNode keyA a, Binary a, Show keyA) => Binary (Graph keyA a) where
134136
put x = put (toList x)
135137
get = fmap fromDistinctList get
136138

137-
instance Structured a => Structured (Graph a) where
139+
instance (Structured a, Typeable keyA) => Structured (Graph keyA a) where
138140
structure p = Nominal (typeRep p) 0 "Graph" [structure (Proxy :: Proxy a)]
139141

140-
instance (Eq (Key a), Eq a) => Eq (Graph a) where
142+
instance (Eq keyA, Eq a) => Eq (Graph keyA a) where
141143
g1 == g2 = graphMap g1 == graphMap g2
142144

143-
instance Foldable.Foldable Graph where
145+
instance Foldable.Foldable (Graph keyA) where
144146
elem x = Foldable.elem x . graphMap
145147
fold = Foldable.fold . graphMap
146148
foldl f z = Foldable.foldl f z . graphMap
@@ -156,7 +158,7 @@ instance Foldable.Foldable Graph where
156158
sum = Foldable.sum . graphMap
157159
toList = Foldable.toList . graphMap
158160

159-
instance (NFData a, NFData (Key a)) => NFData (Graph a) where
161+
instance (NFData a, NFData keyA) => NFData (Graph keyA a) where
160162
rnf
161163
Graph
162164
{ graphMap = m
@@ -173,13 +175,11 @@ instance (NFData a, NFData (Key a)) => NFData (Graph a) where
173175
-- graph nodes. A node of type @a@ is associated with some unique key of
174176
-- type @'Key' a@; given a node we can determine its key ('nodeKey')
175177
-- and the keys of its neighbors ('nodeNeighbors').
176-
class Ord (Key a) => IsNode a where
177-
type Key a
178-
nodeKey :: a -> Key a
179-
nodeNeighbors :: a -> [Key a]
178+
class Ord keyA => IsNode keyA a | a -> keyA where
179+
nodeKey :: a -> keyA
180+
nodeNeighbors :: a -> [keyA]
180181

181-
instance (IsNode a, IsNode b, Key a ~ Key b) => IsNode (Either a b) where
182-
type Key (Either a b) = Key a
182+
instance (IsNode key a, IsNode key b) => IsNode key (Either a b) where
183183
nodeKey (Left x) = nodeKey x
184184
nodeKey (Right x) = nodeKey x
185185
nodeNeighbors (Left x) = nodeNeighbors x
@@ -196,50 +196,49 @@ nodeValue (N a _ _) = a
196196
instance Functor (Node k) where
197197
fmap f (N a k ks) = N (f a) k ks
198198

199-
instance Ord k => IsNode (Node k a) where
200-
type Key (Node k a) = k
199+
instance Ord k => IsNode k (Node k a) where
201200
nodeKey (N _ k _) = k
202201
nodeNeighbors (N _ _ ks) = ks
203202

204203
-- TODO: Maybe introduce a typeclass for items which just
205-
-- keys (so, Key associated type, and nodeKey method). But
204+
-- keys (so, keyAssociated type, and nodeKey method). But
206205
-- I didn't need it here, so I didn't introduce it.
207206

208207
-- Query
209208

210209
-- | /O(1)/. Is the graph empty?
211-
null :: Graph a -> Bool
210+
null :: Graph keyA a -> Bool
212211
null = Map.null . toMap
213212

214213
-- | /O(1)/. The number of nodes in the graph.
215-
size :: Graph a -> Int
214+
size :: Graph keyA a -> Int
216215
size = Map.size . toMap
217216

218217
-- | /O(log V)/. Check if the key is in the graph.
219-
member :: IsNode a => Key a -> Graph a -> Bool
218+
member :: IsNode keyA a => keyA -> Graph keyA a -> Bool
220219
member k g = Map.member k (toMap g)
221220

222221
-- | /O(log V)/. Lookup the node at a key in the graph.
223-
lookup :: IsNode a => Key a -> Graph a -> Maybe a
222+
lookup :: IsNode keyA a => keyA -> Graph keyA a -> Maybe a
224223
lookup k g = Map.lookup k (toMap g)
225224

226225
-- Construction
227226

228227
-- | /O(1)/. The empty graph.
229-
empty :: IsNode a => Graph a
228+
empty :: IsNode keyA a => Graph keyA a
230229
empty = fromMap Map.empty
231230

232231
-- | /O(log V)/. Insert a node into a graph.
233-
insert :: IsNode a => a -> Graph a -> Graph a
232+
insert :: IsNode keyA a => a -> Graph keyA a -> Graph keyA a
234233
insert !n g = fromMap (Map.insert (nodeKey n) n (toMap g))
235234

236235
-- | /O(log V)/. Delete the node at a key from the graph.
237-
deleteKey :: IsNode a => Key a -> Graph a -> Graph a
236+
deleteKey :: IsNode keyA a => keyA -> Graph keyA a -> Graph keyA a
238237
deleteKey k g = fromMap (Map.delete k (toMap g))
239238

240239
-- | /O(log V)/. Lookup and delete. This function returns the deleted
241240
-- value if it existed.
242-
deleteLookup :: IsNode a => Key a -> Graph a -> (Maybe a, Graph a)
241+
deleteLookup :: IsNode keyA a => keyA -> Graph keyA a -> (Maybe a, Graph keyA a)
243242
deleteLookup k g =
244243
let (r, m') = Map.updateLookupWithKey (\_ _ -> Nothing) k (toMap g)
245244
in (r, fromMap m')
@@ -249,19 +248,19 @@ deleteLookup k g =
249248
-- | /O(V + V')/. Right-biased union, preferring entries
250249
-- from the second map when conflicts occur.
251250
-- @'nodeKey' x = 'nodeKey' (f x)@.
252-
unionRight :: IsNode a => Graph a -> Graph a -> Graph a
251+
unionRight :: IsNode keyA a => Graph keyA a -> Graph keyA a -> Graph keyA a
253252
unionRight g g' = fromMap (Map.union (toMap g') (toMap g))
254253

255254
-- | /O(V + V')/. Left-biased union, preferring entries from
256255
-- the first map when conflicts occur.
257-
unionLeft :: IsNode a => Graph a -> Graph a -> Graph a
256+
unionLeft :: IsNode keyA a => Graph keyA a -> Graph keyA a -> Graph keyA a
258257
unionLeft = flip unionRight
259258

260259
-- Graph-like operations
261260

262261
-- | /Ω(V + E)/. Compute the strongly connected components of a graph.
263262
-- Requires amortized construction of graph.
264-
stronglyConnComp :: Graph a -> [SCC a]
263+
stronglyConnComp :: Graph keyA a -> [SCC a]
265264
stronglyConnComp g = map decode forest
266265
where
267266
forest = G.scc (graphForward g)
@@ -278,25 +277,25 @@ stronglyConnComp g = map decode forest
278277

279278
-- | /Ω(V + E)/. Compute the cycles of a graph.
280279
-- Requires amortized construction of graph.
281-
cycles :: Graph a -> [[a]]
280+
cycles :: Graph keyA a -> [[a]]
282281
cycles g = [vs | CyclicSCC vs <- stronglyConnComp g]
283282

284283
-- | /O(1)/. Return a list of nodes paired with their broken
285284
-- neighbors (i.e., neighbor keys which are not in the graph).
286285
-- Requires amortized construction of graph.
287-
broken :: Graph a -> [(a, [Key a])]
286+
broken :: Graph keyA a -> [(a, [keyA])]
288287
broken g = graphBroken g
289288

290289
-- | Lookup the immediate neighbors from a key in the graph.
291290
-- Requires amortized construction of graph.
292-
neighbors :: Graph a -> Key a -> Maybe [a]
291+
neighbors :: Graph keyA a -> keyA -> Maybe [a]
293292
neighbors g k = do
294293
v <- graphKeyToVertex g k
295294
return (map (graphVertexToNode g) (graphForward g ! v))
296295

297296
-- | Lookup the immediate reverse neighbors from a key in the graph.
298297
-- Requires amortized construction of graph.
299-
revNeighbors :: Graph a -> Key a -> Maybe [a]
298+
revNeighbors :: Graph keyA a -> keyA -> Maybe [a]
300299
revNeighbors g k = do
301300
v <- graphKeyToVertex g k
302301
return (map (graphVertexToNode g) (graphAdjoint g ! v))
@@ -305,7 +304,7 @@ revNeighbors g k = do
305304
-- Returns @Nothing@ if one (or more) keys are not present in
306305
-- the graph.
307306
-- Requires amortized construction of graph.
308-
closure :: Graph a -> [Key a] -> Maybe [a]
307+
closure :: Graph keyA a -> [keyA] -> Maybe [a]
309308
closure g ks = do
310309
vs <- traverse (graphKeyToVertex g) ks
311310
return (decodeVertexForest g (G.dfs (graphForward g) vs))
@@ -314,25 +313,25 @@ closure g ks = do
314313
-- of keys. Returns @Nothing@ if one (or more) keys are not present in
315314
-- the graph.
316315
-- Requires amortized construction of graph.
317-
revClosure :: Graph a -> [Key a] -> Maybe [a]
316+
revClosure :: Graph keyA a -> [keyA] -> Maybe [a]
318317
revClosure g ks = do
319318
vs <- traverse (graphKeyToVertex g) ks
320319
return (decodeVertexForest g (G.dfs (graphAdjoint g) vs))
321320

322321
flattenForest :: Tree.Forest a -> [a]
323322
flattenForest = concatMap Tree.flatten
324323

325-
decodeVertexForest :: Graph a -> Tree.Forest G.Vertex -> [a]
324+
decodeVertexForest :: Graph keyA a -> Tree.Forest G.Vertex -> [a]
326325
decodeVertexForest g = map (graphVertexToNode g) . flattenForest
327326

328327
-- | Topologically sort the nodes of a graph.
329328
-- Requires amortized construction of graph.
330-
topSort :: Graph a -> [a]
329+
topSort :: Graph keyA a -> [a]
331330
topSort g = map (graphVertexToNode g) $ G.topSort (graphForward g)
332331

333332
-- | Reverse topologically sort the nodes of a graph.
334333
-- Requires amortized construction of graph.
335-
revTopSort :: Graph a -> [a]
334+
revTopSort :: Graph keyA a -> [a]
336335
revTopSort g = map (graphVertexToNode g) $ G.topSort (graphAdjoint g)
337336

338337
-- Conversions
@@ -343,7 +342,7 @@ revTopSort g = map (graphVertexToNode g) $ G.topSort (graphAdjoint g)
343342
-- if you can't fulfill this invariant use @'fromList' ('Data.Map.elems' m)@
344343
-- instead. The values of the map are assumed to already
345344
-- be in WHNF.
346-
fromMap :: IsNode a => Map (Key a) a -> Graph a
345+
fromMap :: IsNode keyA a => Map keyA a -> Graph keyA a
347346
fromMap m =
348347
Graph
349348
{ graphMap = m
@@ -377,7 +376,7 @@ fromMap m =
377376
bounds = (0, Map.size m - 1)
378377

379378
-- | /O(V log V)/. Convert a list of nodes (with distinct keys) into a graph.
380-
fromDistinctList :: (IsNode a, Show (Key a)) => [a] -> Graph a
379+
fromDistinctList :: (IsNode keyA a, Show keyA) => [a] -> Graph keyA a
381380
fromDistinctList =
382381
fromMap
383382
. Map.fromListWith (\_ -> duplicateError)
@@ -391,26 +390,26 @@ fromDistinctList =
391390
-- Map-like operations
392391

393392
-- | /O(V)/. Convert a graph into a list of nodes.
394-
toList :: Graph a -> [a]
393+
toList :: Graph keyA a -> [a]
395394
toList g = Map.elems (toMap g)
396395

397396
-- | /O(V)/. Convert a graph into a list of keys.
398-
keys :: Graph a -> [Key a]
397+
keys :: Graph keyA a -> [keyA]
399398
keys g = Map.keys (toMap g)
400399

401400
-- | /O(V)/. Convert a graph into a set of keys.
402-
keysSet :: Graph a -> Set.Set (Key a)
401+
keysSet :: Graph keyA a -> Set.Set keyA
403402
keysSet g = Map.keysSet (toMap g)
404403

405404
-- | /O(1)/. Convert a graph into a map from keys to nodes.
406405
-- The resulting map @m@ is guaranteed to have the property that
407406
-- @'Prelude.all' (\(k,n) -> k == 'nodeKey' n) ('Data.Map.toList' m)@.
408-
toMap :: Graph a -> Map (Key a) a
407+
toMap :: Graph keyA a -> Map keyA a
409408
toMap = graphMap
410409

411410
-- Graph-like operations
412411

413412
-- | /O(1)/. Convert a graph into a 'Data.Graph.Graph'.
414413
-- Requires amortized construction of graph.
415-
toGraph :: Graph a -> (G.Graph, G.Vertex -> a, Key a -> Maybe G.Vertex)
414+
toGraph :: Graph keyA a -> (G.Graph, G.Vertex -> a, keyA -> Maybe G.Vertex)
416415
toGraph g = (graphForward g, graphVertexToNode g, graphKeyToVertex g)

Cabal-syntax/src/Distribution/Types/InstalledPackageInfo.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{-# LANGUAGE DeriveGeneric #-}
2+
{-# LANGUAGE MultiParamTypeClasses #-}
23
{-# LANGUAGE OverloadedStrings #-}
3-
{-# LANGUAGE TypeFamilies #-}
44

55
module Distribution.Types.InstalledPackageInfo
66
( InstalledPackageInfo (..)
@@ -113,8 +113,7 @@ instance Package.HasUnitId InstalledPackageInfo where
113113
instance Package.PackageInstalled InstalledPackageInfo where
114114
installedDepends = depends
115115

116-
instance IsNode InstalledPackageInfo where
117-
type Key InstalledPackageInfo = UnitId
116+
instance IsNode UnitId InstalledPackageInfo where
118117
nodeKey = installedUnitId
119118
nodeNeighbors = depends
120119

Cabal-syntax/src/Distribution/Utils/Path.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
{-# LANGUAGE DeriveGeneric #-}
44
{-# LANGUAGE FlexibleInstances #-}
55
{-# LANGUAGE FunctionalDependencies #-}
6+
{-# LANGUAGE KindSignatures #-}
67
{-# LANGUAGE RankNTypes #-}
78
{-# LANGUAGE RoleAnnotations #-}
8-
{-# LANGUAGE TypeFamilies #-}
99
{-# LANGUAGE TypeOperators #-}
1010
{-# LANGUAGE UndecidableInstances #-}
1111

Cabal-syntax/src/Distribution/Utils/Structured.hs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
{-# LANGUAGE PolyKinds #-}
66
{-# LANGUAGE ScopedTypeVariables #-}
77
{-# LANGUAGE TypeApplications #-}
8-
{-# LANGUAGE TypeFamilies #-}
98
{-# LANGUAGE TypeOperators #-}
109

1110
-- |

0 commit comments

Comments
 (0)