Bodigrim pushed to branch wip/nubOrd at Glasgow Haskell Compiler / GHC
Commits:
-
c12fa73e
by Simon Peyton Jones at 2025-11-19T02:55:01-05:00
-
41b84f40
by sheaf at 2025-11-19T02:55:52-05:00
-
1faa758a
by sheaf at 2025-11-19T02:55:52-05:00
-
bddcf63d
by Andrew Lelechenko at 2025-11-19T22:28:46+00:00
19 changed files:
- compiler/GHC/Core/Utils.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/Types/SourceText.hs
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/base/src/Data/List.hs
- libraries/base/src/Data/List/NonEmpty.hs
- + libraries/base/src/Data/List/NubOrdSet.hs
- libraries/ghc-internal/src/GHC/Internal/Data/OldList.hs
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
- + testsuite/tests/linear/should_run/T26311.hs
- + testsuite/tests/linear/should_run/T26311.stdout
- testsuite/tests/linear/should_run/all.T
- testsuite/tests/pmcheck/should_compile/pmcOrPats.stderr
- + testsuite/tests/rep-poly/T26072b.hs
- testsuite/tests/rep-poly/all.T
Changes:
| ... | ... | @@ -78,7 +78,7 @@ import GHC.Core.Type as Type |
| 78 | 78 | import GHC.Core.Predicate( isEqPred )
|
| 79 | 79 | import GHC.Core.Predicate( isUnaryClass )
|
| 80 | 80 | import GHC.Core.FamInstEnv
|
| 81 | -import GHC.Core.TyCo.Compare( eqType, eqTypeX )
|
|
| 81 | +import GHC.Core.TyCo.Compare( eqType, eqTypeX, eqTypeIgnoringMultiplicity )
|
|
| 82 | 82 | import GHC.Core.Coercion
|
| 83 | 83 | import GHC.Core.Reduction
|
| 84 | 84 | import GHC.Core.TyCon
|
| ... | ... | @@ -275,7 +275,7 @@ mkCast expr co |
| 275 | 275 | = assertPpr (coercionRole co == Representational)
|
| 276 | 276 | (text "coercion" <+> ppr co <+> text "passed to mkCast"
|
| 277 | 277 | <+> ppr expr <+> text "has wrong role" <+> ppr (coercionRole co)) $
|
| 278 | - warnPprTrace (not (coercionLKind co `eqType` exprType expr)) "Bad cast"
|
|
| 278 | + warnPprTrace (not (coercionLKind co `eqTypeIgnoringMultiplicity` exprType expr)) "Bad cast"
|
|
| 279 | 279 | (vcat [ text "Coercion LHS kind does not match enclosed expression type"
|
| 280 | 280 | , text "co:" <+> ppr co
|
| 281 | 281 | , text "coercionLKind:" <+> ppr (coercionLKind co)
|
| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | {-# LANGUAGE ScopedTypeVariables #-}
|
| 3 | 3 | {-# LANGUAGE ViewPatterns #-}
|
| 4 | 4 | {-# LANGUAGE MultiWayIf #-}
|
| 5 | +{-# LANGUAGE TypeFamilies #-}
|
|
| 5 | 6 | |
| 6 | 7 | -- | Domain types used in "GHC.HsToCore.Pmc.Solver".
|
| 7 | 8 | -- The ultimate goal is to define 'Nabla', which models normalised refinement
|
| ... | ... | @@ -32,7 +33,7 @@ module GHC.HsToCore.Pmc.Solver.Types ( |
| 32 | 33 | PmEquality(..), eqPmAltCon,
|
| 33 | 34 | |
| 34 | 35 | -- *** Operations on 'PmLit'
|
| 35 | - literalToPmLit, negatePmLit, overloadPmLit,
|
|
| 36 | + literalToPmLit, negatePmLit,
|
|
| 36 | 37 | pmLitAsStringLit, coreExprAsPmLit
|
| 37 | 38 | |
| 38 | 39 | ) where
|
| ... | ... | @@ -51,13 +52,12 @@ import GHC.Core.ConLike |
| 51 | 52 | import GHC.Utils.Outputable
|
| 52 | 53 | import GHC.Utils.Panic.Plain
|
| 53 | 54 | import GHC.Utils.Misc (lastMaybe)
|
| 54 | -import GHC.Data.List.SetOps (unionLists)
|
|
| 55 | 55 | import GHC.Data.Maybe
|
| 56 | 56 | import GHC.Core.Type
|
| 57 | 57 | import GHC.Core.TyCon
|
| 58 | 58 | import GHC.Types.Literal
|
| 59 | 59 | import GHC.Core
|
| 60 | -import GHC.Core.TyCo.Compare( eqType )
|
|
| 60 | +import GHC.Core.TyCo.Compare( eqType, nonDetCmpType )
|
|
| 61 | 61 | import GHC.Core.Map.Expr
|
| 62 | 62 | import GHC.Core.Utils (exprType)
|
| 63 | 63 | import GHC.Builtin.Names
|
| ... | ... | @@ -69,15 +69,14 @@ import GHC.Types.CompleteMatch |
| 69 | 69 | import GHC.Types.SourceText (SourceText(..), mkFractionalLit, FractionalLit
|
| 70 | 70 | , fractionalLitFromRational
|
| 71 | 71 | , FractionalExponentBase(..))
|
| 72 | + |
|
| 72 | 73 | import Numeric (fromRat)
|
| 73 | -import Data.Foldable (find)
|
|
| 74 | 74 | import Data.Ratio
|
| 75 | +import Data.List( find )
|
|
| 76 | +import qualified Data.Map as FM
|
|
| 75 | 77 | import GHC.Real (Ratio(..))
|
| 76 | -import qualified Data.Semigroup as Semi
|
|
| 77 | - |
|
| 78 | --- import GHC.Driver.Ppr
|
|
| 78 | +import qualified Data.Semigroup as S
|
|
| 79 | 79 | |
| 80 | ---
|
|
| 81 | 80 | -- * Normalised refinement types
|
| 82 | 81 | --
|
| 83 | 82 | |
| ... | ... | @@ -358,6 +357,13 @@ lookupSolution nabla x = case vi_pos (lookupVarInfo (nabla_tm_st nabla) x) of |
| 358 | 357 | | Just sol <- find isDataConSolution pos -> Just sol
|
| 359 | 358 | | otherwise -> Just x
|
| 360 | 359 | |
| 360 | + |
|
| 361 | +{- *********************************************************************
|
|
| 362 | +* *
|
|
| 363 | + PmLit and PmLitValue
|
|
| 364 | +* *
|
|
| 365 | +********************************************************************* -}
|
|
| 366 | + |
|
| 361 | 367 | --------------------------------------------------------------------------------
|
| 362 | 368 | -- The rest is just providing an IR for (overloaded!) literals and AltCons that
|
| 363 | 369 | -- sits between Hs and Core. We need a reliable way to detect and determine
|
| ... | ... | @@ -376,13 +382,64 @@ data PmLitValue |
| 376 | 382 | = PmLitInt Integer
|
| 377 | 383 | | PmLitRat Rational
|
| 378 | 384 | | PmLitChar Char
|
| 379 | - -- We won't actually see PmLitString in the oracle since we desugar strings to
|
|
| 380 | - -- lists
|
|
| 381 | 385 | | PmLitString FastString
|
| 386 | + -- We won't actually see PmLitString in the oracle
|
|
| 387 | + -- since we desugar strings to lists
|
|
| 388 | + |
|
| 389 | + -- Overloaded literals
|
|
| 382 | 390 | | PmLitOverInt Int {- How often Negated? -} Integer
|
| 383 | 391 | | PmLitOverRat Int {- How often Negated? -} FractionalLit
|
| 384 | 392 | | PmLitOverString FastString
|
| 385 | 393 | |
| 394 | +-- | Syntactic equality.
|
|
| 395 | +-- We want (Ord PmLit) so that we can use (Map PmLit x) in `PmAltConSet`
|
|
| 396 | +instance Eq PmLit where
|
|
| 397 | + a == b = (a `compare` b) == EQ
|
|
| 398 | +instance Ord PmLit where
|
|
| 399 | + compare = cmpPmLit
|
|
| 400 | + |
|
| 401 | +cmpPmLit :: PmLit -> PmLit -> Ordering
|
|
| 402 | +-- This function does "syntactic comparison":
|
|
| 403 | +-- For overloaded literals, compare the type and value
|
|
| 404 | +-- For non-overloaded literals, just compare the values
|
|
| 405 | +-- But it treats (say)
|
|
| 406 | +-- (PmLit Bool (PmLitOverInt 1))
|
|
| 407 | +-- (PmLit Bool (PmLitOverInt 2))
|
|
| 408 | +-- as un-equal, even through (fromInteger @Bool 1)
|
|
| 409 | +-- could be the same as (fromInteger @Bool 2)
|
|
| 410 | +cmpPmLit (PmLit { pm_lit_ty = t1, pm_lit_val = val1 })
|
|
| 411 | + (PmLit { pm_lit_ty = t2, pm_lit_val = val2 })
|
|
| 412 | + = case (val1,val2) of
|
|
| 413 | + (PmLitInt i1, PmLitInt i2) -> i1 `compare` i2
|
|
| 414 | + (PmLitRat r1, PmLitRat r2) -> r1 `compare` r2
|
|
| 415 | + (PmLitChar c1, PmLitChar c2) -> c1 `compare` c2
|
|
| 416 | + (PmLitString s1, PmLitString s2) -> s1 `uniqCompareFS` s2
|
|
| 417 | + (PmLitOverInt n1 i1, PmLitOverInt n2 i2) -> (n1 `compare` n2) S.<>
|
|
| 418 | + (i1 `compare` i2) S.<>
|
|
| 419 | + (t1 `nonDetCmpType` t2)
|
|
| 420 | + (PmLitOverRat n1 r1, PmLitOverRat n2 r2) -> (n1 `compare` n2) S.<>
|
|
| 421 | + (r1 `compare` r2) S.<>
|
|
| 422 | + (t1 `nonDetCmpType` t2)
|
|
| 423 | + (PmLitOverString s1, PmLitOverString s2) -> (s1 `uniqCompareFS` s2) S.<>
|
|
| 424 | + (t1 `nonDetCmpType` t2)
|
|
| 425 | + (PmLitInt {}, _) -> LT
|
|
| 426 | + (PmLitRat {}, PmLitInt {}) -> GT
|
|
| 427 | + (PmLitRat {}, _) -> LT
|
|
| 428 | + (PmLitChar {}, PmLitInt {}) -> GT
|
|
| 429 | + (PmLitChar {}, PmLitRat {}) -> GT
|
|
| 430 | + (PmLitChar {}, _) -> LT
|
|
| 431 | + (PmLitString {}, PmLitInt {}) -> GT
|
|
| 432 | + (PmLitString {}, PmLitRat {}) -> GT
|
|
| 433 | + (PmLitString {}, PmLitChar {}) -> GT
|
|
| 434 | + (PmLitString {}, _) -> LT
|
|
| 435 | + |
|
| 436 | + (PmLitOverString {}, _) -> GT
|
|
| 437 | + (PmLitOverRat {}, PmLitOverString{}) -> LT
|
|
| 438 | + (PmLitOverRat {}, _) -> GT
|
|
| 439 | + (PmLitOverInt {}, PmLitOverString{}) -> LT
|
|
| 440 | + (PmLitOverInt {}, PmLitOverRat{}) -> LT
|
|
| 441 | + (PmLitOverInt {}, _) -> GT
|
|
| 442 | + |
|
| 386 | 443 | -- | Undecidable semantic equality result.
|
| 387 | 444 | -- See Note [Undecidable Equality for PmAltCons]
|
| 388 | 445 | data PmEquality
|
| ... | ... | @@ -406,7 +463,10 @@ eqPmLit :: PmLit -> PmLit -> PmEquality |
| 406 | 463 | eqPmLit (PmLit t1 v1) (PmLit t2 v2)
|
| 407 | 464 | -- no haddock | pprTrace "eqPmLit" (ppr t1 <+> ppr v1 $$ ppr t2 <+> ppr v2) False = undefined
|
| 408 | 465 | | not (t1 `eqType` t2) = Disjoint
|
| 409 | - | otherwise = go v1 v2
|
|
| 466 | + | otherwise = eqPmLitValue v1 v2
|
|
| 467 | + |
|
| 468 | +eqPmLitValue :: PmLitValue -> PmLitValue -> PmEquality
|
|
| 469 | +eqPmLitValue v1 v2 = go v1 v2
|
|
| 410 | 470 | where
|
| 411 | 471 | go (PmLitInt i1) (PmLitInt i2) = decEquality (i1 == i2)
|
| 412 | 472 | go (PmLitRat r1) (PmLitRat r2) = decEquality (r1 == r2)
|
| ... | ... | @@ -420,10 +480,6 @@ eqPmLit (PmLit t1 v1) (PmLit t2 v2) |
| 420 | 480 | | s1 == s2 = Equal
|
| 421 | 481 | go _ _ = PossiblyOverlap
|
| 422 | 482 | |
| 423 | --- | Syntactic equality.
|
|
| 424 | -instance Eq PmLit where
|
|
| 425 | - a == b = eqPmLit a b == Equal
|
|
| 426 | - |
|
| 427 | 483 | -- | Type of a 'PmLit'
|
| 428 | 484 | pmLitType :: PmLit -> Type
|
| 429 | 485 | pmLitType (PmLit ty _) = ty
|
| ... | ... | @@ -445,34 +501,47 @@ eqConLike (PatSynCon psc1) (PatSynCon psc2) |
| 445 | 501 | = Equal
|
| 446 | 502 | eqConLike _ _ = PossiblyOverlap
|
| 447 | 503 | |
| 504 | + |
|
| 505 | +{- *********************************************************************
|
|
| 506 | +* *
|
|
| 507 | + PmAltCon and PmAltConSet
|
|
| 508 | +* *
|
|
| 509 | +********************************************************************* -}
|
|
| 510 | + |
|
| 448 | 511 | -- | Represents the head of a match against a 'ConLike' or literal.
|
| 449 | 512 | -- Really similar to 'GHC.Core.AltCon'.
|
| 450 | 513 | data PmAltCon = PmAltConLike ConLike
|
| 451 | 514 | | PmAltLit PmLit
|
| 452 | 515 | |
| 453 | -data PmAltConSet = PACS !(UniqDSet ConLike) ![PmLit]
|
|
| 516 | +data PmAltConSet = PACS !(UniqDSet ConLike)
|
|
| 517 | + !(FM.Map PmLit PmLit)
|
|
| 518 | +-- We use a (FM.Map PmLit PmLit) here, at the cost of requiring an Ord
|
|
| 519 | +-- instance for PmLit, because in extreme cases the set of PmLits can be
|
|
| 520 | +-- very large. See #26514.
|
|
| 454 | 521 | |
| 455 | 522 | emptyPmAltConSet :: PmAltConSet
|
| 456 | -emptyPmAltConSet = PACS emptyUniqDSet []
|
|
| 523 | +emptyPmAltConSet = PACS emptyUniqDSet FM.empty
|
|
| 457 | 524 | |
| 458 | 525 | isEmptyPmAltConSet :: PmAltConSet -> Bool
|
| 459 | -isEmptyPmAltConSet (PACS cls lits) = isEmptyUniqDSet cls && null lits
|
|
| 526 | +isEmptyPmAltConSet (PACS cls lits)
|
|
| 527 | + = isEmptyUniqDSet cls && FM.null lits
|
|
| 460 | 528 | |
| 461 | 529 | -- | Whether there is a 'PmAltCon' in the 'PmAltConSet' that compares 'Equal' to
|
| 462 | 530 | -- the given 'PmAltCon' according to 'eqPmAltCon'.
|
| 463 | 531 | elemPmAltConSet :: PmAltCon -> PmAltConSet -> Bool
|
| 464 | 532 | elemPmAltConSet (PmAltConLike cl) (PACS cls _ ) = elementOfUniqDSet cl cls
|
| 465 | -elemPmAltConSet (PmAltLit lit) (PACS _ lits) = elem lit lits
|
|
| 533 | +elemPmAltConSet (PmAltLit lit) (PACS _ lits) = isJust (FM.lookup lit lits)
|
|
| 466 | 534 | |
| 467 | 535 | extendPmAltConSet :: PmAltConSet -> PmAltCon -> PmAltConSet
|
| 468 | 536 | extendPmAltConSet (PACS cls lits) (PmAltConLike cl)
|
| 469 | 537 | = PACS (addOneToUniqDSet cls cl) lits
|
| 470 | 538 | extendPmAltConSet (PACS cls lits) (PmAltLit lit)
|
| 471 | - = PACS cls (unionLists lits [lit])
|
|
| 539 | + = PACS cls (FM.insert lit lit lits)
|
|
| 472 | 540 | |
| 473 | 541 | pmAltConSetElems :: PmAltConSet -> [PmAltCon]
|
| 474 | 542 | pmAltConSetElems (PACS cls lits)
|
| 475 | - = map PmAltConLike (uniqDSetToList cls) ++ map PmAltLit lits
|
|
| 543 | + = map PmAltConLike (uniqDSetToList cls) ++
|
|
| 544 | + FM.foldr ((:) . PmAltLit) [] lits
|
|
| 476 | 545 | |
| 477 | 546 | instance Outputable PmAltConSet where
|
| 478 | 547 | ppr = ppr . pmAltConSetElems
|
| ... | ... | @@ -188,6 +188,7 @@ data FractionalLit = FL |
| 188 | 188 | }
|
| 189 | 189 | deriving (Data, Show)
|
| 190 | 190 | -- The Show instance is required for the derived GHC.Parser.Lexer.Token instance when DEBUG is on
|
| 191 | + -- Eq and Ord instances are done explicitly
|
|
| 191 | 192 | |
| 192 | 193 | -- See Note [FractionalLit representation] in GHC.HsToCore.Match.Literal
|
| 193 | 194 | data FractionalExponentBase
|
| ... | ... | @@ -303,6 +303,7 @@ Library |
| 303 | 303 | , GHC.JS.Foreign.Callback
|
| 304 | 304 | |
| 305 | 305 | other-modules:
|
| 306 | + Data.List.NubOrdSet
|
|
| 306 | 307 | System.CPUTime.Unsupported
|
| 307 | 308 | System.CPUTime.Utils
|
| 308 | 309 | if os(windows)
|
| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | * Fix bug where `naturalAndNot` was incorrectly truncating results ([CLC proposal #350](github.com/haskell/core-libraries-committee/issues/350))
|
| 11 | 11 | * Remove extra laziness from `Data.Bifunctor.Bifunctor` instances for all tuples to have the same laziness as their `Data.Functor.Functor` counterparts (i.e. they became more strict than before) ([CLC proposal #339](https://github.com/haskell/core-libraries-committee/issues/339))
|
| 12 | 12 | * Adjust the strictness of `Data.List.iterate'` to be more reasonable: every element of the output list is forced to WHNF when the `(:)` containing it is forced. ([CLC proposal #335)](https://github.com/haskell/core-libraries-committee/issues/335)
|
| 13 | + * Add `nubOrd` / `nubOrdBy` to `Data.List` and `Data.List.NonEmpty`. ([CLC proposal #336](https://github.com/haskell/core-libraries-committee/issues/336))
|
|
| 13 | 14 | |
| 14 | 15 | ## 4.22.0.0 *TBA*
|
| 15 | 16 | * Shipped with GHC 9.14.1
|
| ... | ... | @@ -137,6 +137,7 @@ module Data.List |
| 137 | 137 | unwords,
|
| 138 | 138 | -- ** \"Set\" operations
|
| 139 | 139 | nub,
|
| 140 | + nubOrd,
|
|
| 140 | 141 | delete,
|
| 141 | 142 | (\\),
|
| 142 | 143 | union,
|
| ... | ... | @@ -157,6 +158,7 @@ module Data.List |
| 157 | 158 | -- *** User-supplied equality (replacing an @Eq@ context)
|
| 158 | 159 | -- | The predicate is assumed to define an equivalence.
|
| 159 | 160 | nubBy,
|
| 161 | + nubOrdBy,
|
|
| 160 | 162 | deleteBy,
|
| 161 | 163 | deleteFirstsBy,
|
| 162 | 164 | unionBy,
|
| ... | ... | @@ -180,12 +182,14 @@ module Data.List |
| 180 | 182 | ) where
|
| 181 | 183 | |
| 182 | 184 | import GHC.Internal.Data.Bool (otherwise)
|
| 185 | +import GHC.Internal.Data.Function (const)
|
|
| 183 | 186 | import GHC.Internal.Data.List
|
| 184 | 187 | import GHC.Internal.Data.List.NonEmpty (NonEmpty(..))
|
| 185 | -import GHC.Internal.Data.Ord (Ordering(..), (<), (>))
|
|
| 188 | +import GHC.Internal.Data.Ord (Ord, compare, Ordering(..), (<), (>))
|
|
| 186 | 189 | import GHC.Internal.Int (Int)
|
| 187 | 190 | import GHC.Internal.Num ((-))
|
| 188 | 191 | import GHC.List (build)
|
| 192 | +import qualified Data.List.NubOrdSet as NubOrdSet
|
|
| 189 | 193 | |
| 190 | 194 | inits1, tails1 :: [a] -> [NonEmpty a]
|
| 191 | 195 | |
| ... | ... | @@ -282,3 +286,24 @@ compareLength xs n |
| 282 | 286 | (\m -> if m > 0 then LT else EQ)
|
| 283 | 287 | xs
|
| 284 | 288 | n
|
| 289 | + |
|
| 290 | +-- | Same as 'nub', but asymptotically faster, taking only /O/(/n/ log /n/) time.
|
|
| 291 | +--
|
|
| 292 | +-- @since 4.23.0.0
|
|
| 293 | +nubOrd :: Ord a => [a] -> [a]
|
|
| 294 | +nubOrd = nubOrdBy compare
|
|
| 295 | +{-# INLINE nubOrd #-}
|
|
| 296 | + |
|
| 297 | +-- | Overloaded version of 'Data.List.nubOrd'.
|
|
| 298 | +--
|
|
| 299 | +-- The supplied comparison relation is supposed to be reflexive, transitive
|
|
| 300 | +-- and antisymmetric, same as for 'sortBy'.
|
|
| 301 | +--
|
|
| 302 | +-- @since 4.23.0.0
|
|
| 303 | +nubOrdBy :: (a -> a -> Ordering) -> [a] -> [a]
|
|
| 304 | +nubOrdBy cmp xs = foldr
|
|
| 305 | + (\x acc seen -> if NubOrdSet.member cmp x seen then acc seen else x : acc (NubOrdSet.insert cmp x seen))
|
|
| 306 | + (const [])
|
|
| 307 | + xs
|
|
| 308 | + NubOrdSet.empty
|
|
| 309 | +{-# INLINE nubOrdBy #-} |
| ... | ... | @@ -94,7 +94,9 @@ module Data.List.NonEmpty ( |
| 94 | 94 | , isPrefixOf -- :: Eq a => [a] -> NonEmpty a -> Bool
|
| 95 | 95 | -- * \"Set\" operations
|
| 96 | 96 | , nub -- :: Eq a => NonEmpty a -> NonEmpty a
|
| 97 | + , nubOrd -- :: Ord a => NonEmpty a -> NonEmpty a
|
|
| 97 | 98 | , nubBy -- :: (a -> a -> Bool) -> NonEmpty a -> NonEmpty a
|
| 99 | + , nubOrdBy -- :: (a -> a -> Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 98 | 100 | -- * Indexing streams
|
| 99 | 101 | , (!!) -- :: NonEmpty a -> Int -> a
|
| 100 | 102 | -- * Zipping and unzipping streams
|
| ... | ... | @@ -119,6 +121,7 @@ import qualified Prelude |
| 119 | 121 | |
| 120 | 122 | import Control.Applicative (Applicative (..), Alternative (many))
|
| 121 | 123 | import qualified Data.List as List
|
| 124 | +import qualified Data.List.NubOrdSet as NubOrdSet
|
|
| 122 | 125 | import qualified Data.Maybe as List (mapMaybe)
|
| 123 | 126 | import GHC.Internal.Data.Foldable hiding (length, toList)
|
| 124 | 127 | import qualified GHC.Internal.Data.Foldable as Foldable
|
| ... | ... | @@ -577,6 +580,24 @@ nub = nubBy (==) |
| 577 | 580 | nubBy :: (a -> a -> Bool) -> NonEmpty a -> NonEmpty a
|
| 578 | 581 | nubBy eq (a :| as) = a :| List.nubBy eq (List.filter (\b -> not (eq a b)) as)
|
| 579 | 582 | |
| 583 | +-- | Same as 'nub', but asymptotically faster, taking only /O/(/n/ log /n/) time.
|
|
| 584 | +--
|
|
| 585 | +-- @since 4.23.0.0
|
|
| 586 | +nubOrd :: Ord a => NonEmpty a -> NonEmpty a
|
|
| 587 | +nubOrd = nubOrdBy compare
|
|
| 588 | +{-# INLINE nubOrd #-}
|
|
| 589 | + |
|
| 590 | +-- | Overloaded version of 'Data.List.NonEmpty.nubOrd'.
|
|
| 591 | +--
|
|
| 592 | +-- @since 4.23.0.0
|
|
| 593 | +nubOrdBy :: (a -> a -> Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 594 | +nubOrdBy cmp (y :| ys) = y :| foldr
|
|
| 595 | + (\x acc seen -> if NubOrdSet.member cmp x seen then acc seen else x : acc (NubOrdSet.insert cmp x seen))
|
|
| 596 | + (const [])
|
|
| 597 | + ys
|
|
| 598 | + (NubOrdSet.insert cmp y NubOrdSet.empty)
|
|
| 599 | +{-# INLINE nubOrdBy #-}
|
|
| 600 | + |
|
| 580 | 601 | -- | 'transpose' for 'NonEmpty', behaves the same as 'GHC.Internal.Data.List.transpose'
|
| 581 | 602 | -- The rows/columns need not be the same length, in which case
|
| 582 | 603 | -- > transpose . transpose /= id
|
| 1 | +-- This is an internal module with a naive set implementation,
|
|
| 2 | +-- solely for the purposes of `Data.List.{,NonEmpty.}nubOrd{,By}`.
|
|
| 3 | + |
|
| 4 | +{-# LANGUAGE BangPatterns #-}
|
|
| 5 | +{-# LANGUAGE LambdaCase #-}
|
|
| 6 | + |
|
| 7 | +module Data.List.NubOrdSet (
|
|
| 8 | + NubOrdSet,
|
|
| 9 | + empty,
|
|
| 10 | + member,
|
|
| 11 | + insert,
|
|
| 12 | +) where
|
|
| 13 | + |
|
| 14 | +import GHC.Internal.Data.Bool (Bool(..))
|
|
| 15 | +import GHC.Internal.Data.Function ((.))
|
|
| 16 | +import GHC.Internal.Data.Ord (Ordering(..))
|
|
| 17 | + |
|
| 18 | +-- | Implemented as a red-black tree, a la Okasaki.
|
|
| 19 | +data NubOrdSet a
|
|
| 20 | + = Empty
|
|
| 21 | + | NodeRed !(NubOrdSet a) !a !(NubOrdSet a)
|
|
| 22 | + | NodeBlack !(NubOrdSet a) !a !(NubOrdSet a)
|
|
| 23 | + |
|
| 24 | +empty :: NubOrdSet a
|
|
| 25 | +empty = Empty
|
|
| 26 | + |
|
| 27 | +member :: (a -> a -> Ordering) -> a -> NubOrdSet a -> Bool
|
|
| 28 | +member cmp = member'
|
|
| 29 | + where
|
|
| 30 | + member' !x = go
|
|
| 31 | + where
|
|
| 32 | + go = \case
|
|
| 33 | + Empty -> False
|
|
| 34 | + NodeRed left center right -> chooseWay left center right
|
|
| 35 | + NodeBlack left center right -> chooseWay left center right
|
|
| 36 | + |
|
| 37 | + chooseWay left center right = case cmp x center of
|
|
| 38 | + LT -> go left
|
|
| 39 | + EQ -> True
|
|
| 40 | + GT -> go right
|
|
| 41 | +{-# INLINE member #-}
|
|
| 42 | + |
|
| 43 | +insert :: (a -> a -> Ordering) -> a -> NubOrdSet a -> NubOrdSet a
|
|
| 44 | +insert cmp = insert'
|
|
| 45 | + where
|
|
| 46 | + insert' !x = blacken . go
|
|
| 47 | + where
|
|
| 48 | + go node = case node of
|
|
| 49 | + Empty -> NodeRed Empty x Empty
|
|
| 50 | + NodeRed left center right -> case cmp x center of
|
|
| 51 | + LT -> NodeRed (go left) center right
|
|
| 52 | + EQ -> node
|
|
| 53 | + GT -> NodeRed left center (go right)
|
|
| 54 | + NodeBlack left center right -> case cmp x center of
|
|
| 55 | + LT -> balanceBlackLeft (go left) center right
|
|
| 56 | + EQ -> node
|
|
| 57 | + GT -> balanceBlackRight left center (go right)
|
|
| 58 | + |
|
| 59 | + blacken node = case node of
|
|
| 60 | + Empty -> Empty
|
|
| 61 | + NodeRed left center right -> NodeBlack left center right
|
|
| 62 | + NodeBlack{} -> node
|
|
| 63 | +{-# INLINE insert #-}
|
|
| 64 | + |
|
| 65 | +balanceBlackLeft :: NubOrdSet a -> a -> NubOrdSet a -> NubOrdSet a
|
|
| 66 | +balanceBlackLeft (NodeRed (NodeRed a b c) d e) f g =
|
|
| 67 | + NodeRed (NodeBlack a b c) d (NodeBlack e f g)
|
|
| 68 | +balanceBlackLeft (NodeRed a b (NodeRed c d e)) f g =
|
|
| 69 | + NodeRed (NodeBlack a b c) d (NodeBlack e f g)
|
|
| 70 | +balanceBlackLeft left center right =
|
|
| 71 | + NodeBlack left center right
|
|
| 72 | +{-# INLINE balanceBlackLeft #-}
|
|
| 73 | + |
|
| 74 | +balanceBlackRight :: NubOrdSet a -> a -> NubOrdSet a -> NubOrdSet a
|
|
| 75 | +balanceBlackRight a b (NodeRed (NodeRed c d e) f g) =
|
|
| 76 | + NodeRed (NodeBlack a b c) d (NodeBlack e f g)
|
|
| 77 | +balanceBlackRight a b (NodeRed c d (NodeRed e f g)) =
|
|
| 78 | + NodeRed (NodeBlack a b c) d (NodeBlack e f g)
|
|
| 79 | +balanceBlackRight left center right =
|
|
| 80 | + NodeBlack left center right
|
|
| 81 | +{-# INLINE balanceBlackRight #-} |
| ... | ... | @@ -499,16 +499,7 @@ isInfixOf needle haystack = any (isPrefixOf needle) (tails haystack) |
| 499 | 499 | -- name 'nub' means \`essence\'.) It is a special case of 'nubBy', which allows
|
| 500 | 500 | -- the programmer to supply their own equality test.
|
| 501 | 501 | --
|
| 502 | ---
|
|
| 503 | --- If there exists @instance Ord a@, it's faster to use `nubOrd` from the `containers` package
|
|
| 504 | --- ([link to the latest online documentation](https://hackage.haskell.org/package/containers/docs/Data-Containers-ListUtils.html#v:nubOrd)),
|
|
| 505 | --- which takes only \(\mathcal{O}(n \log d)\) time where `d` is the number of
|
|
| 506 | --- distinct elements in the list.
|
|
| 507 | ---
|
|
| 508 | --- Another approach to speed up 'nub' is to use
|
|
| 509 | --- 'map' @Data.List.NonEmpty.@'Data.List.NonEmpty.head' . @Data.List.NonEmpty.@'Data.List.NonEmpty.group' . 'sort',
|
|
| 510 | --- which takes \(\mathcal{O}(n \log n)\) time, requires @instance Ord a@ and doesn't
|
|
| 511 | --- preserve the order.
|
|
| 502 | +-- If there exists @instance Ord a@, it's faster to use 'Data.List.nubOrd'.
|
|
| 512 | 503 | --
|
| 513 | 504 | -- ==== __Examples__
|
| 514 | 505 | --
|
| ... | ... | @@ -1379,6 +1379,8 @@ module Data.List where |
| 1379 | 1379 | notElem :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Classes.Eq a) => a -> t a -> GHC.Internal.Types.Bool
|
| 1380 | 1380 | nub :: forall a. GHC.Internal.Classes.Eq a => [a] -> [a]
|
| 1381 | 1381 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> [a] -> [a]
|
| 1382 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => [a] -> [a]
|
|
| 1383 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> [a] -> [a]
|
|
| 1382 | 1384 | null :: forall (t :: * -> *) a. GHC.Internal.Data.Foldable.Foldable t => t a -> GHC.Internal.Types.Bool
|
| 1383 | 1385 | or :: forall (t :: * -> *). GHC.Internal.Data.Foldable.Foldable t => t GHC.Internal.Types.Bool -> GHC.Internal.Types.Bool
|
| 1384 | 1386 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> [a] -> ([a], [a])
|
| ... | ... | @@ -1473,6 +1475,8 @@ module Data.List.NonEmpty where |
| 1473 | 1475 | nonEmpty :: forall a. [a] -> GHC.Internal.Maybe.Maybe (NonEmpty a)
|
| 1474 | 1476 | nub :: forall a. GHC.Internal.Classes.Eq a => NonEmpty a -> NonEmpty a
|
| 1475 | 1477 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> NonEmpty a -> NonEmpty a
|
| 1478 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => NonEmpty a -> NonEmpty a
|
|
| 1479 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 1476 | 1480 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> NonEmpty a -> ([a], [a])
|
| 1477 | 1481 | permutations :: forall a. [a] -> NonEmpty [a]
|
| 1478 | 1482 | permutations1 :: forall a. NonEmpty a -> NonEmpty (NonEmpty a)
|
| ... | ... | @@ -1379,6 +1379,8 @@ module Data.List where |
| 1379 | 1379 | notElem :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Classes.Eq a) => a -> t a -> GHC.Internal.Types.Bool
|
| 1380 | 1380 | nub :: forall a. GHC.Internal.Classes.Eq a => [a] -> [a]
|
| 1381 | 1381 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> [a] -> [a]
|
| 1382 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => [a] -> [a]
|
|
| 1383 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> [a] -> [a]
|
|
| 1382 | 1384 | null :: forall (t :: * -> *) a. GHC.Internal.Data.Foldable.Foldable t => t a -> GHC.Internal.Types.Bool
|
| 1383 | 1385 | or :: forall (t :: * -> *). GHC.Internal.Data.Foldable.Foldable t => t GHC.Internal.Types.Bool -> GHC.Internal.Types.Bool
|
| 1384 | 1386 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> [a] -> ([a], [a])
|
| ... | ... | @@ -1473,6 +1475,8 @@ module Data.List.NonEmpty where |
| 1473 | 1475 | nonEmpty :: forall a. [a] -> GHC.Internal.Maybe.Maybe (NonEmpty a)
|
| 1474 | 1476 | nub :: forall a. GHC.Internal.Classes.Eq a => NonEmpty a -> NonEmpty a
|
| 1475 | 1477 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> NonEmpty a -> NonEmpty a
|
| 1478 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => NonEmpty a -> NonEmpty a
|
|
| 1479 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 1476 | 1480 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> NonEmpty a -> ([a], [a])
|
| 1477 | 1481 | permutations :: forall a. [a] -> NonEmpty [a]
|
| 1478 | 1482 | permutations1 :: forall a. NonEmpty a -> NonEmpty (NonEmpty a)
|
| ... | ... | @@ -1379,6 +1379,8 @@ module Data.List where |
| 1379 | 1379 | notElem :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Classes.Eq a) => a -> t a -> GHC.Internal.Types.Bool
|
| 1380 | 1380 | nub :: forall a. GHC.Internal.Classes.Eq a => [a] -> [a]
|
| 1381 | 1381 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> [a] -> [a]
|
| 1382 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => [a] -> [a]
|
|
| 1383 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> [a] -> [a]
|
|
| 1382 | 1384 | null :: forall (t :: * -> *) a. GHC.Internal.Data.Foldable.Foldable t => t a -> GHC.Internal.Types.Bool
|
| 1383 | 1385 | or :: forall (t :: * -> *). GHC.Internal.Data.Foldable.Foldable t => t GHC.Internal.Types.Bool -> GHC.Internal.Types.Bool
|
| 1384 | 1386 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> [a] -> ([a], [a])
|
| ... | ... | @@ -1473,6 +1475,8 @@ module Data.List.NonEmpty where |
| 1473 | 1475 | nonEmpty :: forall a. [a] -> GHC.Internal.Maybe.Maybe (NonEmpty a)
|
| 1474 | 1476 | nub :: forall a. GHC.Internal.Classes.Eq a => NonEmpty a -> NonEmpty a
|
| 1475 | 1477 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> NonEmpty a -> NonEmpty a
|
| 1478 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => NonEmpty a -> NonEmpty a
|
|
| 1479 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 1476 | 1480 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> NonEmpty a -> ([a], [a])
|
| 1477 | 1481 | permutations :: forall a. [a] -> NonEmpty [a]
|
| 1478 | 1482 | permutations1 :: forall a. NonEmpty a -> NonEmpty (NonEmpty a)
|
| ... | ... | @@ -1379,6 +1379,8 @@ module Data.List where |
| 1379 | 1379 | notElem :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Classes.Eq a) => a -> t a -> GHC.Internal.Types.Bool
|
| 1380 | 1380 | nub :: forall a. GHC.Internal.Classes.Eq a => [a] -> [a]
|
| 1381 | 1381 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> [a] -> [a]
|
| 1382 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => [a] -> [a]
|
|
| 1383 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> [a] -> [a]
|
|
| 1382 | 1384 | null :: forall (t :: * -> *) a. GHC.Internal.Data.Foldable.Foldable t => t a -> GHC.Internal.Types.Bool
|
| 1383 | 1385 | or :: forall (t :: * -> *). GHC.Internal.Data.Foldable.Foldable t => t GHC.Internal.Types.Bool -> GHC.Internal.Types.Bool
|
| 1384 | 1386 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> [a] -> ([a], [a])
|
| ... | ... | @@ -1473,6 +1475,8 @@ module Data.List.NonEmpty where |
| 1473 | 1475 | nonEmpty :: forall a. [a] -> GHC.Internal.Maybe.Maybe (NonEmpty a)
|
| 1474 | 1476 | nub :: forall a. GHC.Internal.Classes.Eq a => NonEmpty a -> NonEmpty a
|
| 1475 | 1477 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> NonEmpty a -> NonEmpty a
|
| 1478 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => NonEmpty a -> NonEmpty a
|
|
| 1479 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 1476 | 1480 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> NonEmpty a -> ([a], [a])
|
| 1477 | 1481 | permutations :: forall a. [a] -> NonEmpty [a]
|
| 1478 | 1482 | permutations1 :: forall a. NonEmpty a -> NonEmpty (NonEmpty a)
|
| 1 | +{-# LANGUAGE MagicHash #-}
|
|
| 2 | + |
|
| 3 | +module Main where
|
|
| 4 | + |
|
| 5 | +import GHC.Exts ( Int# )
|
|
| 6 | + |
|
| 7 | +expensive :: Int -> Int#
|
|
| 8 | +expensive 0 = 2#
|
|
| 9 | +expensive i = expensive (i-1)
|
|
| 10 | + |
|
| 11 | +data D = MkD Int# Int
|
|
| 12 | + |
|
| 13 | +f :: a -> Bool
|
|
| 14 | +f _ = False
|
|
| 15 | +{-# NOINLINE f #-}
|
|
| 16 | + |
|
| 17 | +{-# RULES "f/MkD" forall x. f (MkD x) = True #-}
|
|
| 18 | + |
|
| 19 | +bar :: Bool
|
|
| 20 | +bar = f (MkD (expensive 10))
|
|
| 21 | + |
|
| 22 | +main :: IO ()
|
|
| 23 | +main = print bar |
| 1 | +True |
| 1 | 1 | test('LinearTypeable', normal, compile_and_run, [''])
|
| 2 | +test('T26311', normal, compile_and_run, ['-O1'])
|
|
| 2 | 3 | test('LinearGhci', normal, ghci_script, ['LinearGhci.script']) |
| 1 | - |
|
| 2 | 1 | pmcOrPats.hs:10:1: warning: [GHC-62161] [-Wincomplete-patterns (in -Wextra)]
|
| 3 | 2 | Pattern match(es) are non-exhaustive
|
| 4 | 3 | In an equation for ‘g’: Patterns of type ‘T’, ‘U’ not matched: A W
|
| ... | ... | @@ -18,7 +17,7 @@ pmcOrPats.hs:15:1: warning: [GHC-53633] [-Woverlapping-patterns (in -Wdefault)] |
| 18 | 17 | pmcOrPats.hs:17:1: warning: [GHC-62161] [-Wincomplete-patterns (in -Wextra)]
|
| 19 | 18 | Pattern match(es) are non-exhaustive
|
| 20 | 19 | In an equation for ‘z’:
|
| 21 | - Patterns of type ‘a’ not matched: p where p is not one of {3, 1, 2}
|
|
| 20 | + Patterns of type ‘a’ not matched: p where p is not one of {1, 2, 3}
|
|
| 22 | 21 | |
| 23 | 22 | pmcOrPats.hs:19:1: warning: [GHC-53633] [-Woverlapping-patterns (in -Wdefault)]
|
| 24 | 23 | Pattern match is redundant
|
| ... | ... | @@ -43,3 +42,4 @@ pmcOrPats.hs:21:1: warning: [GHC-61505] |
| 43 | 42 | • Patterns reported as unmatched might actually be matched
|
| 44 | 43 | Suggested fix:
|
| 45 | 44 | Increase the limit or resolve the warnings to suppress this message.
|
| 45 | + |
| 1 | +{-# LANGUAGE AllowAmbiguousTypes #-}
|
|
| 2 | +{-# LANGUAGE BangPatterns #-}
|
|
| 3 | +{-# LANGUAGE BlockArguments #-}
|
|
| 4 | +{-# LANGUAGE DataKinds #-}
|
|
| 5 | +{-# LANGUAGE MagicHash #-}
|
|
| 6 | +{-# LANGUAGE PolyKinds #-}
|
|
| 7 | +{-# LANGUAGE ScopedTypeVariables #-}
|
|
| 8 | +{-# LANGUAGE StandaloneKindSignatures #-}
|
|
| 9 | +{-# LANGUAGE TypeApplications #-}
|
|
| 10 | +{-# LANGUAGE TypeFamilies #-}
|
|
| 11 | +{-# LANGUAGE UnboxedTuples #-}
|
|
| 12 | + |
|
| 13 | +module T26072b where
|
|
| 14 | + |
|
| 15 | +-- base
|
|
| 16 | +import Data.Kind
|
|
| 17 | +import GHC.TypeNats
|
|
| 18 | +import GHC.Exts
|
|
| 19 | + ( TYPE, RuntimeRep(..), LiftedRep
|
|
| 20 | + , proxy#
|
|
| 21 | + )
|
|
| 22 | + |
|
| 23 | +--------------------------------------------------------------------------------
|
|
| 24 | + |
|
| 25 | +-- Stub for functions in 'primitive' (to avoid dependency)
|
|
| 26 | +type PrimArray :: Type -> Type
|
|
| 27 | +data PrimArray a = MkPrimArray
|
|
| 28 | + |
|
| 29 | +indexPrimArray :: PrimArray a -> Int -> a
|
|
| 30 | +indexPrimArray _ _ = error "unimplemented"
|
|
| 31 | +{-# NOINLINE indexPrimArray #-}
|
|
| 32 | + |
|
| 33 | +--------------------------------------------------------------------------------
|
|
| 34 | + |
|
| 35 | +int :: forall n. KnownNat n => Int
|
|
| 36 | +int = fromIntegral ( natVal' @n proxy# )
|
|
| 37 | + |
|
| 38 | +type Fin :: Nat -> Type
|
|
| 39 | +newtype Fin n = Fin { getFin :: Int }
|
|
| 40 | + |
|
| 41 | +-- Vector
|
|
| 42 | +type V :: Nat -> Type -> Type
|
|
| 43 | +newtype V n a = V ( PrimArray a )
|
|
| 44 | + |
|
| 45 | +-- Matrix
|
|
| 46 | +type M :: Nat -> Type -> Type
|
|
| 47 | +newtype M n a = M ( PrimArray a )
|
|
| 48 | + |
|
| 49 | +type IndexRep :: (Type -> Type) -> RuntimeRep
|
|
| 50 | +type family IndexRep f
|
|
| 51 | +class Ix f where
|
|
| 52 | + type Index f :: TYPE (IndexRep f)
|
|
| 53 | + (!) :: f a -> Index f -> a
|
|
| 54 | + infixl 9 !
|
|
| 55 | + |
|
| 56 | +type instance IndexRep ( V n ) = LiftedRep
|
|
| 57 | +instance Ix ( V n ) where
|
|
| 58 | + type Index ( V n ) = Fin n
|
|
| 59 | + V v ! Fin !i = indexPrimArray v i
|
|
| 60 | + {-# INLINE (!) #-}
|
|
| 61 | + |
|
| 62 | +type instance IndexRep ( M m ) = TupleRep [ LiftedRep, LiftedRep ]
|
|
| 63 | + |
|
| 64 | +instance KnownNat n => Ix ( M n ) where
|
|
| 65 | + type Index ( M n ) = (# Fin n, Fin n #)
|
|
| 66 | + M m ! (# Fin !i, Fin !j #) = indexPrimArray m ( i + j * int @n )
|
|
| 67 | + {-# INLINE (!) #-}
|
|
| 68 | + |
|
| 69 | +rowCol :: forall n a. ( KnownNat n, Num a ) => Fin n -> M n a -> V n a -> a
|
|
| 70 | +rowCol i m v = go 0 ( Fin 0 )
|
|
| 71 | + where
|
|
| 72 | + n = int @n
|
|
| 73 | + go :: a -> Fin n -> a
|
|
| 74 | + go !acc j@( Fin !j_ )
|
|
| 75 | + | j_ >= n
|
|
| 76 | + = acc
|
|
| 77 | + | otherwise
|
|
| 78 | + = go ( acc + m ! (# i , j #) * v ! j ) ( Fin ( j_ + 1 ) ) |
| ... | ... | @@ -127,6 +127,7 @@ test('T17536b', normal, compile, ['']) ## |
| 127 | 127 | test('T21650_a', js_broken(26578), compile, ['-Wno-deprecated-flags']) ##
|
| 128 | 128 | test('T21650_b', js_broken(26578), compile, ['-Wno-deprecated-flags']) ##
|
| 129 | 129 | test('T26072', js_broken(26578), compile, ['']) ##
|
| 130 | +test('T26072b', js_broken(26578), compile, ['']) ##
|
|
| 130 | 131 | test('RepPolyArgument2', normal, compile, ['']) ##
|
| 131 | 132 | test('RepPolyCase2', js_broken(26578), compile, ['']) ##
|
| 132 | 133 | test('RepPolyRule3', normal, compile, ['']) ##
|