diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c69237a..9064c86 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,30 +6,24 @@ on: pull_request: branches: [master] +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - - uses: purescript-contrib/setup-purescript@main - with: - purescript: "unstable" + - uses: actions/checkout@v6 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v6 with: - node-version: "14.x" + node-version: "24" - name: Install dependencies - run: | - npm install -g bower - npm install - bower install --production + run: npm install - name: Build source - run: npm run-script build + run: npm run build - - name: Run tests - run: | - bower install - npm run-script test --if-present + - name: Check formatting + run: npm run format:check diff --git a/.gitignore b/.gitignore index 673c789..afb2a45 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,9 @@ /.* !/.gitignore !/.github/ -package-lock.json +!/.tidyrc.json +/package-lock.json +/spago.lock /bower_components/ /node_modules/ /output/ -package-lock.json diff --git a/.tidyrc.json b/.tidyrc.json new file mode 100644 index 0000000..9e39cf1 --- /dev/null +++ b/.tidyrc.json @@ -0,0 +1,10 @@ +{ + "importSort": "ide", + "importWrap": "source", + "indent": 2, + "operatorsFile": null, + "ribbon": 1, + "typeArrowPlacement": "first", + "unicode": "never", + "width": null +} diff --git a/CHANGELOG.md b/CHANGELOG.md index afdc974..9c01967 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ Notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [Unreleased](https://github.com/purescript/purescript-typelevel-prelude/compare/v7.0.1...HEAD) Breaking changes: @@ -12,13 +12,22 @@ Bugfixes: Other improvements: +## [v7.0.1](https://github.com/purescript/purescript-typelevel-prelude/releases/tag/v7.0.1) - 2026-10-17 + +Other improvements: + +- Migrate from Bower/Pulp to Spago and update CI (#76 by @thomashoneyman) +- Fix comment typos (#75 by @i-am-the-slime) + ## [v7.0.0](https://github.com/purescript/purescript-typelevel-prelude/releases/tag/v7.0.0) - 2022-04-27 Breaking changes: + - Update project and deps to PureScript v0.15.0 (#72 by @JordanMartinez) - Replaced polymorphic proxies with monomorphic `Proxy` (#72 by @JordanMartinez) New features: + - Added `#` infix operator for `FLIP` (e.g. `Int # Maybe` == `Maybe Int`) (#73 by @JordanMartinez) Bugfixes: @@ -28,17 +37,20 @@ Other improvements: ## [v6.0.0](https://github.com/purescript/purescript-typelevel-prelude/releases/tag/v6.0.0) - 2021-02-26 Breaking changes: + - Added support for PureScript 0.14 and dropped support for all previous versions (#63) New features: + - Replaced monomorphic proxies with `Type.Proxy.Proxy` and polymorphic variables and made `If` and `TypeEquals` polykinded (#64) - Added `APPLY`/`$` and `FLIP` type aliases (#63) - - The type `Foo (Bar Baz)` is the same as `Foo $ Bar Baz` - - The type `Either a b` is the same as `FLIP Either b a` + - The type `Foo (Bar Baz)` is the same as `Foo $ Bar Baz` + - The type `Either a b` is the same as `FLIP Either b a` Bugfixes: Other improvements: + - Migrated CI to GitHub Actions and updated installation instructions to use Spago (#67) - Added a changelog and pull request template (#68, #69) diff --git a/bower.json b/bower.json deleted file mode 100644 index efb1eac..0000000 --- a/bower.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "purescript-typelevel-prelude", - "homepage": "https://github.com/purescript/purescript-typelevel-prelude", - "description": "Types and kinds for basic type-level programming", - "license": "BSD-3-Clause", - "repository": { - "type": "git", - "url": "https://github.com/purescript/purescript-typelevel-prelude.git" - }, - "ignore": [ - "**/.*", - "bower_components", - "node_modules", - "output", - "bower.json", - "package.json" - ], - "dependencies": { - "purescript-prelude": "^6.0.0", - "purescript-type-equality": "^4.0.1" - } -} diff --git a/package.json b/package.json index 3e28704..4efa348 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,14 @@ { "private": true, "scripts": { - "clean": "rimraf output && rimraf .pulp-cache", - "build": "pulp build -- --censor-lib --strict" + "build": "spago build", + "format": "purs-tidy format-in-place src && oxfmt --write .", + "format:check": "purs-tidy check src && oxfmt --check ." }, "devDependencies": { - "pulp": "16.0.0-0", - "purescript-psa": "^0.8.2", - "rimraf": "^3.0.2" + "oxfmt": "^0.73.0", + "purescript": "^0.15.16", + "purs-tidy": "^0.11.1", + "spago": "^1.0.5" } } diff --git a/spago.yaml b/spago.yaml new file mode 100644 index 0000000..4bb4e9b --- /dev/null +++ b/spago.yaml @@ -0,0 +1,16 @@ +package: + name: typelevel-prelude + description: Types and kinds for basic type-level programming + build: + strict: true + pedanticPackages: true + publish: + version: 7.0.1 + license: BSD-3-Clause + location: + githubOwner: purescript + githubRepo: purescript-typelevel-prelude + dependencies: + - prelude: ">=6.0.0 <7.0.0" + - type-equality: ">=4.0.1 <5.0.0" +workspace: {} diff --git a/src/Type/Data/Boolean.purs b/src/Type/Data/Boolean.purs index b56d8a2..135cf86 100644 --- a/src/Type/Data/Boolean.purs +++ b/src/Type/Data/Boolean.purs @@ -13,7 +13,7 @@ module Type.Data.Boolean , if_ ) where -import Prim.Boolean (True, False) +import Prim.Boolean (False, True) import Type.Proxy (Proxy(..)) -- | Class for reflecting a type level `Boolean` at the value level @@ -21,17 +21,22 @@ class IsBoolean :: Boolean -> Constraint class IsBoolean bool where reflectBoolean :: Proxy bool -> Boolean -instance isBooleanTrue :: IsBoolean True where reflectBoolean _ = true -instance isBooleanFalse :: IsBoolean False where reflectBoolean _ = false +instance isBooleanTrue :: IsBoolean True where + reflectBoolean _ = true + +instance isBooleanFalse :: IsBoolean False where + reflectBoolean _ = false -- | Use a value level `Boolean` as a type-level `Boolean` reifyBoolean :: forall r. Boolean -> (forall o. IsBoolean o => Proxy o -> r) -> r -reifyBoolean true f = f (Proxy :: Proxy True) -reifyBoolean false f = f (Proxy :: Proxy False) +reifyBoolean bool f = case bool of + true -> f (Proxy :: Proxy True) + false -> f (Proxy :: Proxy False) -- | And two `Boolean` types together class And :: Boolean -> Boolean -> Boolean -> Constraint class And lhs rhs out | lhs rhs -> out + instance andTrue :: And True rhs rhs instance andFalse :: And False rhs False @@ -41,6 +46,7 @@ and _ _ = Proxy -- | Or two `Boolean` types together class Or :: Boolean -> Boolean -> Boolean -> Constraint class Or lhs rhs output | lhs rhs -> output + instance orTrue :: Or True rhs True instance orFalse :: Or False rhs rhs @@ -50,6 +56,7 @@ or _ _ = Proxy -- | Not a `Boolean` class Not :: Boolean -> Boolean -> Constraint class Not bool output | bool -> output + instance notTrue :: Not True False instance notFalse :: Not False True @@ -59,6 +66,7 @@ not _ = Proxy -- | If - dispatch based on a boolean class If :: forall k. Boolean -> k -> k -> k -> Constraint class If bool onTrue onFalse output | bool onTrue onFalse -> output + instance ifTrue :: If True onTrue onFalse onTrue instance ifFalse :: If False onTrue onFalse onFalse diff --git a/src/Type/Data/Ordering.purs b/src/Type/Data/Ordering.purs index 5dd15cb..ec95a6c 100644 --- a/src/Type/Data/Ordering.purs +++ b/src/Type/Data/Ordering.purs @@ -11,9 +11,9 @@ module Type.Data.Ordering , equals ) where -import Prim.Ordering (LT, EQ, GT, Ordering) as PO import Data.Ordering (Ordering(..)) -import Type.Data.Boolean (True, False) +import Prim.Ordering (EQ, GT, LT, Ordering) as PO +import Type.Data.Boolean (False, True) import Type.Proxy (Proxy(..)) -- | Class for reflecting a type level `Ordering` at the value level @@ -21,20 +21,27 @@ class IsOrdering :: PO.Ordering -> Constraint class IsOrdering ordering where reflectOrdering :: Proxy ordering -> Ordering -instance isOrderingLT :: IsOrdering PO.LT where reflectOrdering _ = LT -instance isOrderingEQ :: IsOrdering PO.EQ where reflectOrdering _ = EQ -instance isOrderingGT :: IsOrdering PO.GT where reflectOrdering _ = GT +instance isOrderingLT :: IsOrdering PO.LT where + reflectOrdering _ = LT + +instance isOrderingEQ :: IsOrdering PO.EQ where + reflectOrdering _ = EQ + +instance isOrderingGT :: IsOrdering PO.GT where + reflectOrdering _ = GT -- | Use a value level `Ordering` as a type-level `Ordering` reifyOrdering :: forall r. Ordering -> (forall o. IsOrdering o => Proxy o -> r) -> r -reifyOrdering LT f = f (Proxy :: Proxy PO.LT) -reifyOrdering EQ f = f (Proxy :: Proxy PO.EQ) -reifyOrdering GT f = f (Proxy :: Proxy PO.GT) +reifyOrdering ordering f = case ordering of + LT -> f (Proxy :: Proxy PO.LT) + EQ -> f (Proxy :: Proxy PO.EQ) + GT -> f (Proxy :: Proxy PO.GT) -- | Append two `Ordering` types together -- | Reflective of the semigroup for value level `Ordering` class Append :: PO.Ordering -> PO.Ordering -> PO.Ordering -> Constraint class Append lhs rhs output | lhs -> rhs output + instance appendOrderingLT :: Append PO.LT rhs PO.LT instance appendOrderingEQ :: Append PO.EQ rhs rhs instance appendOrderingGT :: Append PO.GT rhs PO.GT @@ -45,6 +52,7 @@ append _ _ = Proxy -- | Invert an `Ordering` class Invert :: PO.Ordering -> PO.Ordering -> Constraint class Invert ordering result | ordering -> result + instance invertOrderingLT :: Invert PO.LT PO.GT instance invertOrderingEQ :: Invert PO.EQ PO.EQ instance invertOrderingGT :: Invert PO.GT PO.LT diff --git a/src/Type/Data/Symbol.purs b/src/Type/Data/Symbol.purs index 535ae49..18303b9 100644 --- a/src/Type/Data/Symbol.purs +++ b/src/Type/Data/Symbol.purs @@ -8,10 +8,10 @@ module Type.Data.Symbol , equals ) where -import Prim.Symbol (class Append, class Compare, class Cons) import Data.Symbol (class IsSymbol, reflectSymbol, reifySymbol) -import Type.Data.Ordering (EQ) +import Prim.Symbol (class Append, class Compare, class Cons) import Type.Data.Ordering (class Equals) as Ordering +import Type.Data.Ordering (EQ) import Type.Proxy (Proxy(..)) compare :: forall l r o. Compare l r o => Proxy l -> Proxy r -> Proxy o @@ -20,16 +20,17 @@ compare _ _ = Proxy append :: forall l r o. Append l r o => Proxy l -> Proxy r -> Proxy o append _ _ = Proxy -uncons :: forall h t s. Cons h t s => Proxy s -> {head :: Proxy h, tail :: Proxy t} -uncons _ = {head : Proxy, tail : Proxy} +uncons :: forall h t s. Cons h t s => Proxy s -> { head :: Proxy h, tail :: Proxy t } +uncons _ = { head: Proxy, tail: Proxy } class Equals :: Symbol -> Symbol -> Boolean -> Constraint class Equals lhs rhs out | lhs rhs -> out -instance equalsSymbol - :: (Compare lhs rhs ord, - Ordering.Equals EQ ord out) - => Equals lhs rhs out +instance equalsSymbol :: + ( Compare lhs rhs ord + , Ordering.Equals EQ ord out + ) => + Equals lhs rhs out equals :: forall l r o. Equals l r o => Proxy l -> Proxy r -> Proxy o equals _ _ = Proxy diff --git a/src/Type/Prelude.purs b/src/Type/Prelude.purs index f67d0a2..ee445b7 100644 --- a/src/Type/Prelude.purs +++ b/src/Type/Prelude.purs @@ -8,10 +8,10 @@ module Type.Prelude , module Type.RowList ) where -import Type.Data.Boolean (True, False, class IsBoolean, reflectBoolean, reifyBoolean) -import Type.Data.Ordering (Ordering, LT, EQ, GT, class IsOrdering, reflectOrdering, reifyOrdering) -import Type.Proxy (Proxy(..)) -import Type.Data.Symbol (class IsSymbol, reflectSymbol, reifySymbol, class Compare, compare, class Append, append) +import Type.Data.Boolean (class IsBoolean, False, True, reflectBoolean, reifyBoolean) +import Type.Data.Ordering (class IsOrdering, EQ, GT, LT, Ordering, reflectOrdering, reifyOrdering) +import Type.Data.Symbol (class Append, class Compare, class IsSymbol, append, compare, reflectSymbol, reifySymbol) import Type.Equality (class TypeEquals, from, to) -import Type.Row (class Union, class Lacks) -import Type.RowList (class RowToList, class ListToRow) +import Type.Proxy (Proxy(..)) +import Type.Row (class Lacks, class Union) +import Type.RowList (class ListToRow, class RowToList) diff --git a/src/Type/Row.purs b/src/Type/Row.purs index 101cb9d..3d84f2a 100644 --- a/src/Type/Row.purs +++ b/src/Type/Row.purs @@ -4,7 +4,7 @@ module Type.Row , type (+) ) where -import Prim.Row (class Lacks, class Nub, class Cons, class Union) +import Prim.Row (class Cons, class Lacks, class Nub, class Union) -- | Type application for rows. type RowApply :: forall k. (Row k -> Row k) -> Row k -> Row k diff --git a/src/Type/Row/Homogeneous.purs b/src/Type/Row/Homogeneous.purs index 69e1cb7..ec0b2e3 100644 --- a/src/Type/Row/Homogeneous.purs +++ b/src/Type/Row/Homogeneous.purs @@ -9,15 +9,20 @@ import Type.RowList (class RowToList, Cons, Nil, RowList) -- | Ensure that every field in a row has the same type. class Homogeneous :: forall k. Row k -> k -> Constraint class Homogeneous row fieldType | row -> fieldType -instance homogeneous - :: ( RowToList row fields - , HomogeneousRowList fields fieldType ) - => Homogeneous row fieldType + +instance homogeneous :: + ( RowToList row fields + , HomogeneousRowList fields fieldType + ) => + Homogeneous row fieldType class HomogeneousRowList :: forall k. RowList k -> k -> Constraint class HomogeneousRowList rowList fieldType | rowList -> fieldType -instance homogeneousRowListCons - :: ( HomogeneousRowList tail fieldType - , TypeEquals fieldType fieldType2 ) - => HomogeneousRowList (Cons symbol fieldType tail) fieldType2 + +instance homogeneousRowListCons :: + ( HomogeneousRowList tail fieldType + , TypeEquals fieldType fieldType2 + ) => + HomogeneousRowList (Cons symbol fieldType tail) fieldType2 + instance homogeneousRowListNil :: HomogeneousRowList Nil fieldType diff --git a/src/Type/RowList.purs b/src/Type/RowList.purs index 07b22f5..38ff391 100644 --- a/src/Type/RowList.purs +++ b/src/Type/RowList.purs @@ -8,75 +8,73 @@ module Type.RowList ) where import Prim.Row as Row -import Prim.RowList (RowList, Cons, Nil, class RowToList) -import Type.Equality (class TypeEquals) -import Type.Data.Symbol as Symbol +import Prim.RowList (class RowToList, Cons, Nil, RowList) import Type.Data.Boolean as Boolean +import Type.Data.Symbol as Symbol +import Type.Equality (class TypeEquals) -- | Convert a RowList to a row of types. -- | The inverse of this operation is `RowToList`. class ListToRow :: forall k. RowList k -> Row k -> Constraint class ListToRow list row | list -> row -instance listToRowNil - :: ListToRow Nil () +instance listToRowNil :: ListToRow Nil () -instance listToRowCons - :: ( ListToRow tail tailRow - , Row.Cons label ty tailRow row ) - => ListToRow (Cons label ty tail) row +instance listToRowCons :: + ( ListToRow tail tailRow + , Row.Cons label ty tailRow row + ) => + ListToRow (Cons label ty tail) row -- | Remove all occurrences of a given label from a RowList class RowListRemove :: forall k. Symbol -> RowList k -> RowList k -> Constraint class RowListRemove label input output | label input -> output -instance rowListRemoveNil - :: RowListRemove label Nil Nil +instance rowListRemoveNil :: RowListRemove label Nil Nil -instance rowListRemoveCons - :: ( RowListRemove label tail tailOutput - , Symbol.Equals label key eq - , Boolean.If eq - tailOutput - (Cons key head tailOutput) - output - ) - => RowListRemove label (Cons key head tail) output +instance rowListRemoveCons :: + ( RowListRemove label tail tailOutput + , Symbol.Equals label key eq + , Boolean.If eq tailOutput (Cons key head tailOutput) output + ) => + RowListRemove label (Cons key head tail) output -- | Add a label to a RowList after removing other occurrences. class RowListSet :: forall k. Symbol -> k -> RowList k -> RowList k -> Constraint class RowListSet label typ input output | label typ input -> output -instance rowListSetImpl - :: ( TypeEquals label label' - , TypeEquals typ typ' - , RowListRemove label input lacking ) - => RowListSet label typ input (Cons label' typ' lacking) +instance rowListSetImpl :: + ( TypeEquals label label' + , TypeEquals typ typ' + , RowListRemove label input lacking + ) => + RowListSet label typ input (Cons label' typ' lacking) -- | Remove label duplicates, keeps earlier occurrences. class RowListNub :: forall k. RowList k -> RowList k -> Constraint class RowListNub input output | input -> output -instance rowListNubNil - :: RowListNub Nil Nil +instance rowListNubNil :: RowListNub Nil Nil -instance rowListNubCons - :: ( TypeEquals label label' - , TypeEquals head head' - , TypeEquals nubbed nubbed' - , RowListRemove label tail removed - , RowListNub removed nubbed ) - => RowListNub (Cons label head tail) (Cons label' head' nubbed') +instance rowListNubCons :: + ( TypeEquals label label' + , TypeEquals head head' + , TypeEquals nubbed nubbed' + , RowListRemove label tail removed + , RowListNub removed nubbed + ) => + RowListNub (Cons label head tail) (Cons label' head' nubbed') -- Append two row lists together class RowListAppend :: forall k. RowList k -> RowList k -> RowList k -> Constraint class RowListAppend lhs rhs out | lhs rhs -> out -instance rowListAppendNil - :: TypeEquals rhs out - => RowListAppend Nil rhs out +instance rowListAppendNil :: + TypeEquals rhs out => + RowListAppend Nil rhs out -instance rowListAppendCons - :: ( RowListAppend tail rhs out' - , TypeEquals (Cons label head out') out ) - => RowListAppend (Cons label head tail) rhs out +instance rowListAppendCons :: + ( RowListAppend tail rhs out' + , TypeEquals (Cons label head out') out + ) => + RowListAppend (Cons label head tail) rhs out