úÎyén˜      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~  € ‚ ƒ „ … † ‡ ˆ ‰ Š ‹ Œ Ž ‘ ’ “ ” • – — (c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone7<FTChooses an appropriate  for a given key type.MonoMapGs should all be ordered maps, which feature efficient variants of the  and  combinators. This unifies  Data.Maybe, Data.IntMap.Strict, Data.Map.Strict and Data.POMap.Strictg under a common type class, for which instances can delegate to the most efficient variant available. Because of D, this class lends itself well to approximating monotone functions.(The default implementation delegates to ˜€, so when there is no specially crafted map data-structure for your key type, all you need to do is to make sure it satisfies ™. Then you can doimport Data.IntSetinstance MonoMapKey IntSet*to make use of the default implementation.BThe particular ordered map implementation to use for the key type k.(The default implementation delegates to ˜.^Key point of this interface! Note that it returns a list of lower bounds, to account for the ™ case. Delegates to š. Delegates to ›.      (c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone0<‚œ7Highest priority node and lowest element of the domain k first.žŸ ¡¢£¤¥œ¦§¨©ª«ž(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone0<ô ¬­®¯°±²³´µ¬­(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone&'+,-;<=FQSTV!.A representation of the quantified constraint  forall a. p a. Given that a :- b(, derive something that needs a context b, using the context a1(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone"ˆ¶·¸¹º»¶¼½¾(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone&'+,-;<=>?FSTVh5—  Currying as b# witnesses the isomorphism between  Arrows as b and Products as -> bO. It is defined as a type class rather than by recursion on a singleton for asX so all of that these conversions are inlined at compile time for concrete arguments.$Using IsBase we can define notions of  ParamTypes and  ReturnTypes. which *reduce* under positive information IsBase t ~ 'True even though the shape of t is not formally exposed%IsBase t is 'True whenever t is *not* a function space.& Products [] corresponds to (),  Products [a] corresponds to a, Products [a1,..,an] corresponds to (a1, (..,( an)..)).`So, not quite a right fold, because we want to optimize for the empty, singleton and pair case.'Arrows [a1,..,an] r corresponds to a1 -> .. -> an -> r, Version of FoldrV taking a defunctionalised argument so that we can use partially applied functions.-On Lists. On Booleans/All p as ensures that the constraint p is satisfied by all the types in asZ. (Types is between scare-quotes here because the code is actually kind polymorphic) !"#$%&'()*+,-./0/.-,+*)('0&%$#"! 321 (c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNoneST9ο entailment for ChangeDetectors.À entailment for  LiftedFuncs.Á# entailment for abortion functions. entailment for pure functions.¿ÀÁÂ(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone+<>?FQTVh}§4)A constraint synonym for constraints the domain has to suffice.IThis is actually a lot less scary than you might think. Assuming we got  +http://i.cs.hku.hk/~bruno/papers/hs2017.pdfquantified class constraints instead of hackery from the  _https://hackage.haskell.org/package/constraints-0.10/docs/Data-Constraint-Forall.html#t:ForallF@constraints@ package,  Datafixable" is a specialized version of this: ¨type Datafixable domain = ( forall r. Currying (ParamTypes domain) r , MonoMapKey (Products (ParamTypes domain)) , BoundedJoinSemiLattice (ReturnType domain) ) Now, let's assume a concrete domain ~ String -> Bool -> Int , so that $ (String -> Bool -> Int) expands to the type-level list '[String, Bool] and & '[String, Bool] reduces to (String, Bool)..Then this constraint makes sure we are able to Curry the domain of String -> Bool -> r for all r to e.g. (String, Bool) -> r . See a. This constraint should always be discharged automatically by the type-checker as soon as $ and  ReturnTypes reduce for the 61 argument, which happens when the concrete MonadDependency m is known.We want to use a  0https://en.wikipedia.org/wiki/Monotonic_functionmonotone map of (String, Bool) to Int (the ReturnType domain ). This is ensured by the  (String, Bool) constraint.uThis constraint has to be discharged manually, but should amount to a single line of boiler-plate in most cases, see .WNote that the monotonicity requirement means we have to pull non-monotone arguments in Domain m into the Node portion of the DataFlowProblem.nFor fixed-point iteration to work at all, the values which we iterate naturally have to be instances of ÃL. That type-class allows us to start iteration from a most-optimistic Äj value and successively iterate towards a conservative approximation using the '(/)' operator.5A monad with an associated 6G. This class exists mostly to share the associated type-class between MonadDependency and  MonadDatafix.Also it implies that m satisfies 4, which is common enough6àThe abstract domain in which nodes of the data-flow graph are denoted. When this reduces to a function, then all functions of this domain are assumed to be monotone wrt. the (at least) partial order of all occuring types!NIf you can't guarantee monotonicity, try to pull non-monotone arguments into Nodes.79A function that checks points of some function with type domain for changes. If this returns Å7, the point of the function is assumed to have changed.SAn example is worth a thousand words, especially because of the type-level hackery:5cd = (\a b -> even a /= even b) :: ChangeDetector Int}This checks the parity for changes in the abstract domain of integers. Integers of the same parity are considered unchanged.cd 4 5Truecd 7 13False&Now a (quite bogus) pointwise example:Jcd = (\x fx gx -> x + abs fx /= x + abs gx) :: ChangeDetector (Int -> Int) cd 1 (-1) 1False cd 15 1 2Truecd 13 35 (-35)FalseThis would consider functions id and negate unchanged, so the sequence iterate negate :: Int -> Int- would be regarded immediately as convergent:f x = iterate negate x !! 0let g x = iterate negate x !! 1cd 123 (f 123) (g 123)False8Data-flow problems denote Node9s in the data-flow graph by monotone transfer functions.This type alias alone carries no semantic meaning. However, it is instructive to see some examples of how this alias reduces to a normal form: ´ LiftedFunc Int m ~ m Int LiftedFunc (Bool -> Int) m ~ Bool -> m Int LiftedFunc (a -> b -> Int) m ~ a -> b -> m Int LiftedFunc (a -> b -> c -> Int) m ~ a -> b -> c -> m Int m" will generally be an instance of MonadDependency' and the type alias effectively wraps m around domainw's return type. The result is a function that produces its return value while potentially triggering side-effects in m!, which amounts to depending on 8 s of other Node s for the MonadDependency case.9A 7 that delegates to the Æ instance of the node values.:A 7 that always returns Å.ŽUse this when recomputing a node is cheaper than actually testing for the change. Beware of cycles in the resulting dependency graph, though!456789:879:56456(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone <>?FQTV±Y;'A monad with a single impure primitive <# that expresses a dependency on a A of a data-flow graph.The associated 61 type is the abstract domain in which we denote As.eThink of it like memoization on steroids. You can represent dynamic programs with this quite easily::{[ transferFib :: forall m . (MonadDependency m, Domain m ~ Int) => Node -> LiftedFunc Int m! transferFib (Node 0) = return 0! transferFib (Node 1) = return 1V transferFib (Node n) = (+) <$> dependOn @m (Node (n-1)) <*> dependOn @m (Node (n-2))& -- sparing the negative n error case:}$We can construct a description of a = with this  transferFib function::{X dataFlowProblem :: forall m . (MonadDependency m, Domain m ~ Int) => DataFlowProblem mJ dataFlowProblem = DFP transferFib (const (eqChangeDetector @(Domain m))):}We regard the ordinary fib2 function a solution to the recurrence modeled by  transferFib::{ fib :: Int -> Int fib 0 = 0 fib 1 = 1! fib n = fib (n-1) + fib (n - 2):}E.g., under the assumption of fibj being total (which is true on the domain of natural numbers), it computes the same results as the least  fixed-point7 of the series of iterations of the transfer function  transferFib.!Ostensibly, the nth iteration of  transferFib substitutes each dependOn with  transferFib? repeatedly for n times and finally substitutes all remaining dependOns with a call to Ç.Computing a solution by fixed-point iteration† in a declarative manner is the purpose of this library. There potentially are different approaches to computing a solution, but in Datafix.Worklist‰ we offer an approach based on a worklist algorithm, trying to find a smart order in which nodes in the data-flow graph are reiterated.®The concrete MonadDependency depends on the solution algorithm, which is in fact the reason why there is no satisfying data type in this module: We are only concerned with  declaring data-flow problems here.’The distinguishing feature of data-flow graphs is that they are not necessarily acyclic (data-flow graphs of dynamic programs always are!), but  8https://en.wikipedia.org/wiki/Kleene_fixed-point_theoremunder certain conditions, even have solutions when there are cycles.ÛCycles occur commonly in data-flow problems of static analyses for programming languages, introduced through loops or recursive functions. Thus, this library mostly aims at making the life of compiler writers easier.<ŽExpresses a dependency on a node of the data-flow graph, thus introducing a way of trackable recursion. That's similar to how you would use  to abstract over recursion.='Models a data-flow problem, where each A is mapped to its denoting 8] and a means to detect when the iterated transfer function reached a fixed-point through a 7.?A transfer function per each A" of the modeled data-flow problem.@A 7 for each AT of the modeled data-flow problem. In the simplest case, this just delegates to an Æ instance.A>This is the type we use to index nodes in the data-flow graph..The connection between syntactic things (e.g. Ids) and Ags is made implicitly in code in analysis templates through an appropriate allocation mechanism as in  NodeAllocator. ;<=>?@ABC ABC=>?@;<;<=>?@ABC(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNoneKºFG&A state monad wrapping a mapping from A to some v+ which we will instantiate to appropriate  LiftedFuncs.HAllocates the next A4, which is greater than any nodes requested before.1The value stored at that node is the result of a G+ computation which may already access the Aˆ associated with that value. This is important for the case of recursive let, where the denotation of an expression depends on itself.I4Runs the allocator, beginning with an empty mapping.GHIGHIGÈÉ(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone <FQTVhÍM4A denotation of some syntactic entity in a semantic domain, built in a some N context.NBuilds on an associated O that is a 5 (like any MonadDependency=) by providing a way to track dependencies without explicit NodeE management. Essentially, this allows to specify a build plan for a DataFlowProblem through calls to P in analogy to fix or mfix.OZThe monad in which data dependencies are expressed. Can and will be instantiated to some MonadDependency, if you choose to go through ProblemBuilder.PCThis is the closest we can get to an actual fixed-point combinator.We need to provide a 7¿ for detecting the fixed-point as well as a function to be iterated. In addition to returning a better approximation of itself in terms of itself, it can return an arbitrary value of type a.. Because the iterated function might want to PU additional times (think of nested let bindings), the return values are wrapped in m.Finally, the arbitrary a" value is returned, in analogy to a in # :: MonadFix m => (a -> m a) -> m a.Q!Shorthand that partially applies P to an 9.MNOPQNOPQMNOP(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone;<=>?FKQTVhÔÈRConstructs a build plan for a = by tracking allocation of A s mapping to 7s and transfer functions.S'(root, max, dfp) = buildProblem builder' executes the build plan specified by builder and returns the resulting = dfp, as well as the root A1 denoting the transfer function returned by the R action and the max7imum node of the problem as a proof for its denseness.RSRSRÊË (c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone0<FTßß XBAbstracts over the concrete representation of the data-flow graph.%There are two instances: The default  for sparse graphs based on an IntMap and " for the dense case, storing the Node mapping in a .\Diff between two ¬s.`MThe data associated with each point in the transfer function of a data-flow Node.b The value at this point. Can be Ì only when a loop was detected.c6Points this point of the transfer function depends on.dPoints depending on this point.eBThe number of times this point has been updated through calls to updateNodeValue.f The default `.gComputes the diff between two ¬s.XY[Z\]_^`aedcbfg`abcdef\]^_gXYZ[XYZ[\]^_`abcde (c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone<FTäRj4Reference to a dense data-flow graph representation.Í@Models the points of a transfer function of a single data-flow Node.kAllocates a new dense graph j.jkjkjÎ (c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone<FTèm5Reference to a sparse data-flow graph representation.Ï'Models a data-flow graph as a map from Node3s to associated points of their transfer function.nAllocates a new sparse graph m.mnmnmÐ (c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone&'+<>?FKQTV]h]qplExpresses that iteration should or shouldn't stop after a point has been iterated a finite number of times.qnWill keep on iterating until a precise, yet conservative approximation has been reached. Make sure that your domain satisfies the  7https://en.wikipedia.org/wiki/Ascending_chain_conditionascending chain condition:, e.g. that fixed-point iteration always comes to a halt!rFor when your domaine doesn't satisfy the ascending chain condition or when you are sensitive about solution performance.The ÑIeger determines the maximum number of iterations of a single point of a Aƒ (with which an entire function with many points may be associated) before iteration aborts in that point by calling the supplied s. The responsibility of the s[ is to find a sufficiently conservative approximation for the current value at that point. When your " is an instance of Ò, ‚¢ might be a worthwhile option. A more sophisticated solution would trim the current value to a certain cut-off depth, depending on the first parameter, instead.s¶A function that computes a sufficiently conservative approximation of a point in the abstract domain for when the solution algorithm decides to have iterated the node often enough.When domain is a )'BoundedMeetSemilattice'/'BoundedLattice'@, the simplest abortion function would be to constantly return Ó.As is the case for 8 and 7x, this carries little semantic meaning if viewed in isolation, so here are a few examples for how the synonym expands: ± AbortionFunction Int ~ Int -> Int AbortionFunction (String -> Int) ~ String -> Int -> Int AbortionFunction (a -> b -> c -> PowerSet) ~ a -> b -> c -> PowerSet -> PowerSet =E.g., the current value of the point is passed in (the tuple (a, b, c, PowerSet)U) and the function returns an appropriate conservative approximation in that point.tSpecifies the density- of the problem, e.g. whether the domain of A3s can be confined to a finite range, in which case ‘ tries to use a  Data.Vector6 based graph representation rather than one based on  Data.IntMap.wThe iteration state of 'DependencyM'/'solveProblem'.yHConstant. The specification of the data-flow problem we ought to solve.z@Constant. Whether to abort after a number of iterations or not.{,Contextual state. The set of points in the domain of As currently in the call stack.|^Constant ref to stateful graph. The data-flow graph, modeling dependencies between data-flow A%s, or rather specific points in the domain of each A.}QConstant (but the the wrapped set is stateful). The set of points the currently Šd node references so far.~OConstant (but the the wrapped queue is stateful). Unstable nodes that will be Š d by the list algorithm. The concrete ; for this worklist-based solver.JThis essentially tracks the current approximation of the solution to the = as mutable state while ‘G makes sure we will eventually halt with a conservative approximation.€Why does this use Ô? Actually, we only need STS here, but that means we have to carry around the state thread in type signatures.;This ultimately leaks badly into the exported interface in ‘W: Since we can't have universally quantified instance contexts (yet!), we can' write `(forall s. Datafixable domain => (forall s. DataFlowProblem (DependencyM s graph domain)) -> ...+ and have to instead have the isomorphic o(forall s r. (Datafixable domain => r) -> r) -> (forall s. DataFlowProblem (DependencyM s graph domain)) -> ...0 and urge all call sites to pass a meaningless Õ parameter.bAlso, this means more explicit type signatures as we have to make clear to the type-checker that s@ is universally quantified in everything that touches it, e.g. #Analyses.StrAnal.LetDn.buildProblem from the test suite.So, bottom line: We resort to Ô and ÖE and promise not to launch missiles. In particular, we don't export €. and also there must never be an instance of MonadIO for this.‚Aborts iteration of a value by ×antly returning the Ó element of the assumed Ò of the ".Š4The first of the two major functions of this module.recompute node args" iterates the value of the passed node at the point argsK by invoking its transfer function. It does so in a way that respects the p.5This function is not exported, and is only called by  and ‹4, for when the iteration strategy decides that the nodeF needs to be (and can be) re-iterated. It performs tracking of which AVs the transfer function depended on, do that the worklist algorithm can do its magic.ŒšCompute an optimistic approximation for a point of a given node that is as precise as possible, given the other points of that node we already computed.#E.g., it is always valid to return Ä– from this, but in many cases we can be more precise since we possibly have computed points for the node that are lower bounds to the current point.scheme 1 (see  Œhttps://github.com/sgraf812/journal/blob/09f0521dbdf53e7e5777501fc868bb507f5ceb1a/datafix.md.html#how-an-algorithm-that-can-do-3-looks-like).-Let the worklist algorithm figure things out.Žscheme 2 (see  Œhttps://github.com/sgraf812/journal/blob/09f0521dbdf53e7e5777501fc868bb507f5ceb1a/datafix.md.html#how-an-algorithm-that-can-do-3-looks-like). Descend into \bot nodes when there is no cycle to discover the set of reachable nodes as quick as possible. Do *not* descend into unstable, non-(bot) nodes.As long as the supplied Maybeb expression returns "Just _", the loop body will be called and passed the value contained in the Ø. Results are discarded. Taken from .ODefined as 'work = whileJust_ highestPriorityUnstableNode (uncurry recompute)'.Tries to dequeue the ˆ and Šs the value of one of its ~V points, until the worklist is empty, indicating that a fixed-point has been reached.‘%Computes a solution to the described =A by iterating transfer functions until a fixed-point is reached.AIt does do by employing a worklist algorithm, iterating unstable A s only. A,s become unstable when the point of another A their transfer function ‹ ed changed.The sole initially unstable A% is the last parameter, and if your domain% is function-valued (so the returned 'U expands to a function), then any further parameters specify the exact point in the A+s transfer function you are interested in.1If your problem only has finitely many different As , consider using the ProblemBuilder API (e.g. datafix + evalDenotation6) for a higher-level API that let's you forget about AMs and instead let's you focus on building more complex data-flow frameworks.’This allows us to solve &MonadDependency m => DataFlowProblem m descriptions with ‘.“The 6$ is extracted from a type parameter.‘The description of the DataFlowProblem to solve.,Describes if the algorithm is free to use a v, Vector1-based graph representation or has to go with a u one based on IntMap.kWhether the solution algorithm should respect a maximum bound on the number of iterations per point. Pass q if you don't care.The Node? that is initially assumed to be unstable. This should be the Node you are interested in, e.g. Node 42( if you are interested in the value of fib 42 for a hypothetical  fibProblem , or the NodeP denoting the root expression of your data-flow analysis you specified via the DataFlowProblem."prqstuvwx~}zy|{€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘$€wxyz{|}~“’tuvs‚pqrƒ„…†‡ˆ‰Š‹ŒŽ‘pqrtuvwxyz{|}~€ (c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone <>?FQTViI—evalDenotation denot ib returns a value in domain& that is described by the denotation denot.It does so by building up the DataFlowProblem corresponding to denot) and solving the resulting problem with ‘e, the documentation of which describes in detail how to arrive at a stable denotation and what the p ib is for.—oA build plan for computing the denotation, possibly involving fixed-point iteration factored through calls to P.kWhether the solution algorithm should respect a maximum bound on the number of iterations per point. Pass q if you don't care.——(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNoneja pqrtvu‘— tuvpqr‘—(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNone <>?FTVl; !"#$%&'()*+,-./0456789:;<=>?@ABCGHIMNOPQRSpqrtvu‘—(c) Sebastian Graf 2018ISCsgraf1337@gmail.comportableNonemýÙ !"#$%&'()*+,-./01234556789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_``abcdefghijklmnopqrstu v w & ' x x y z { { | } ~  € ‚ ƒ  „ …  „ … † ‡ ˆ ‰ Š ‹ Œ   Ž ‘ ’ “ ” • – — ˜ ™ š › œ ž Ÿ [   ¡ ¢  £ ¤ ¥ ¦ § ¨ © ª«¬­®¯°±²³´µ¶·¸J¹"#$%&)*,+-/'º»"#$%¼)½·¾¿ÀÁÂþÄÅÆÇÈÉ®ÊË®ÊÌÍÎÏÍÐÑ´ÒÓeÔpÕ´µÖ ×  Ø ÍÎÙ®ÊÚ®ÊÛÍÎÜ´µÝ´Þß´µà´µáâ&datafix-0.0.0.2-1VMHtXTxbcqG4txlxtl1a5Datafix.MonoMapDatafix.Utils.ConstraintsDatafix.Utils.TypeLevelDatafix.CommonDatafix.ExplicitDatafix.NodeAllocatorDatafix.DenotationalDatafix.ProblemBuilderDatafix.Worklist.GraphDatafix.Worklist.Graph.DenseDatafix.Worklist.Graph.SparseDatafix.Worklist.InternalDatafix.Worklist.DenotationalDatafix.IntArgsMonoMapDatafix.IntArgsMonoSetDatafix.Utils.GrowableVectorDatafix.Entailments Data.FunctionfixControl.Monad.FixmfixDatafix.Graph.SparseRefDatafix.Graph.DenseDataIOVectorControl.Monad.Loops whileJust_Datafix.WorklistDatafixDatafix.Tutorial MonoMapKeyMonoMapempty singletoninsertdeletelookuplookupLT lookupMin differencekeys insertWithinsertLookupWithKeyupdateLookupWithKeyalteradjust$fMonoMapKeyInt$fMonoMapKey()Forall:-SubDict\\inst $fForall_kpApply Constant1 Constant0FunctionCurryinguncurryscurrys ReturnType' ReturnType ParamTypes' ParamTypesIsBaseProductsArrowsConstantConsMap1ConsMap0MapFoldr'FoldrIfAll arrowsAxiom $fCurrying:b $fCurrying:b0 $fCurrying[]b Datafixable MonadDomainDomainChangeDetector LiftedFunceqChangeDetectoralwaysChangeDetectorMonadDependencydependOnDataFlowProblemDFP dfpTransferdfpDetectChangeNode unwrapNode$fEqNode $fOrdNode $fShowNode NodeAllocator allocateNode runAllocator$fFunctorNodeAllocator$fApplicativeNodeAllocator$fMonadNodeAllocator Denotation MonadDatafixDepMdatafix datafixEqProblemBuilder buildProblem$fMonadDatafixProblemBuilder$fFunctorProblemBuilder$fApplicativeProblemBuilder$fMonadProblemBuilderGraphRef updatePointDiffaddedremoved PointInfovalue references referrers iterationsemptyPointInfo computeDiff$fShowPointInfo $fEqPointInfonewRef $fGraphRefRefIterationBound NeverAbort AbortAfterAbortionFunctionDensitySparseDenseEnvproblemiterationBound callStackgraphreferencedPointsunstable DependencyMDM initialEnv abortWithTop zoomIORefzoomReferencedPoints zoomUnstableenqueueUnstabledeleteUnstablehighestPriorityUnstableNodewithCall recomputeoptimisticApproximationscheme1scheme2work solveProblem$fMonadDependencyDependencyM$fMonadDomainDependencyM$fFunctorDependencyM$fApplicativeDependencyM$fMonadDependencyMevalDenotation%pomaps-0.0.0.4-3R96Cj2APzxDYXR47xbQRoData.POMap.InternalPOMap%lattices-1.7.1-4FHPjPf0UCiJ8nZIgeRc9oAlgebra.PartialOrd PartialOrdcontainers-0.5.10.2Data.IntMap.InternalIntMapbaseGHC.BaseMaybehighestPriorityNodesIntArgsMonoMapnothingIfEmptyIntArgsMonoSetSetmembertoListGrowableVectornewlengthpushBackwritefreezebufferlencdInstlfInstafInstidInstAlgebra.LatticeBoundedJoinSemiLatticebottomghc-prim GHC.TypesTrue GHC.ClassesEqGHC.ErrerrorunwrapNodeAllocatorunwrapProblemBuilderNothingPointMapGraphIntBoundedMeetSemiLatticetopIOid GHC.IO.UnsafeunsafePerformIOconstJust