diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 0000000000..f5fcfbfda2
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,20 @@
+# Introduce Scalafmt
+774fb51d1365e1adef7fa71f09b1410941264f60
+
+# Migrate to new kind-projector symbol
+e053e287f092126328ffe7eb268281c81c041eed
+
+# Scalafmt updates
+54a6f26b178f490d3816c5eac6d2256228bb065e
+8d98a602a7c2b01b26e9935bfecb0e7f2bbd6737
+4836a55c872a4f931b7f8678f98d9009ed3df84a
+48e1a5a5af3bda6b2f99cd55bda00e14ef71aea7
+f025b0198d55d7f5c09ee976eec9e274d8dd0309
+1531bf8f3c1b1ecd7e37f1548c5e2756a9d52767
+6044f9569c62944aa2c2f4d6eca84cb9d7ca0d15
+
+# Scala Steward: Reformat with scalafmt 3.5.9
+b4d207e9fa9f1463f0827fe20101e7901fecf820
+
+# Scala Steward: Reformat with scalafmt 3.8.4
+42490f49d2a62289c8ca0a57357f323982eeb93b
diff --git a/.github/release.yml b/.github/release.yml
new file mode 100644
index 0000000000..a9bb0dcc2c
--- /dev/null
+++ b/.github/release.yml
@@ -0,0 +1,31 @@
+changelog:
+ categories:
+
+ - title: Features
+ labels:
+ - enhancement
+
+ - title: Optimizations
+ labels:
+ - optimization
+
+ - title: Fixes
+ labels:
+ - bug
+
+ - title: Deprecations
+ labels:
+ - deprecation
+
+ - title: Documentation
+ labels:
+ - documentation
+
+ - title: Behind-the-scenes
+ labels:
+ - behind-the-scenes
+
+ # Not for published notes, just to make sure we don't forget any accidentally unlabeled PRs
+ - title: Uncategorized
+ labels:
+ - "*"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b0e1a03e16..e7f4fc611d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,213 +9,516 @@ name: Continuous Integration
on:
pull_request:
- branches: ['**']
+ branches: ['**', '!update/**', '!pr/**']
push:
- branches: ['**']
+ branches: ['**', '!update/**', '!pr/**']
+ tags: [v*]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- JABBA_INDEX: 'https://github.com/typelevel/jdk-index/raw/main/index.json'
+
+
+concurrency:
+ group: ${{ github.workflow }} @ ${{ github.ref }}
+ cancel-in-progress: true
jobs:
build:
- name: Build and Test
+ name: Test
strategy:
matrix:
- os: [ubuntu-latest]
- scala: [2.12.15, 2.13.7, 3.0.2]
- java:
- - adoptium@8
- - adoptium@17
- - graalvm-ce-java8@21.2
- platform: [jvm, js, native]
+ os: [ubuntu-22.04]
+ scala: [2.12, 2.13, 3]
+ java: [temurin@8, temurin@17, graalvm@21]
+ project: [catsNative, catsJS, catsJVM]
exclude:
- - platform: js
- java: adoptium@17
- - platform: native
- java: adoptium@17
- - platform: js
- java: graalvm-ce-java8@21.2
- - platform: native
- java: graalvm-ce-java8@21.2
- - platform: native
- scala: 3.0.2
+ - scala: 2.12
+ java: temurin@17
+ - scala: 2.12
+ java: graalvm@21
+ - scala: 3
+ java: temurin@17
+ - scala: 3
+ java: graalvm@21
+ - project: catsNative
+ java: temurin@17
+ - project: catsNative
+ java: graalvm@21
+ - project: catsJS
+ java: temurin@17
+ - project: catsJS
+ java: graalvm@21
runs-on: ${{ matrix.os }}
+ timeout-minutes: 60
steps:
- name: Checkout current branch (full)
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- - name: Setup Java and Scala
- uses: olafurpg/setup-scala@v13
+ - name: Setup sbt
+ uses: sbt/setup-sbt@v1
+
+ - name: Setup Java (temurin@8)
+ id: setup-java-temurin-8
+ if: matrix.java == 'temurin@8'
+ uses: actions/setup-java@v4
with:
- java-version: ${{ matrix.java }}
+ distribution: temurin
+ java-version: 8
+ cache: sbt
+
+ - name: sbt update
+ if: matrix.java == 'temurin@8' && steps.setup-java-temurin-8.outputs.cache-hit == 'false'
+ run: sbt +update
- - name: Cache sbt
- uses: actions/cache@v2
+ - name: Setup Java (temurin@17)
+ id: setup-java-temurin-17
+ if: matrix.java == 'temurin@17'
+ uses: actions/setup-java@v4
with:
- path: |
- ~/.sbt
- ~/.ivy2/cache
- ~/.coursier/cache/v1
- ~/.cache/coursier/v1
- ~/AppData/Local/Coursier/Cache/v1
- ~/Library/Caches/Coursier/v1
- key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }}
+ distribution: temurin
+ java-version: 17
+ cache: sbt
- - name: Check that workflows are up to date
- run: sbt ++${{ matrix.scala }} githubWorkflowCheck
+ - name: sbt update
+ if: matrix.java == 'temurin@17' && steps.setup-java-temurin-17.outputs.cache-hit == 'false'
+ run: sbt +update
+
+ - name: Setup Java (graalvm@21)
+ id: setup-java-graalvm-21
+ if: matrix.java == 'graalvm@21'
+ uses: actions/setup-java@v4
+ with:
+ distribution: graalvm
+ java-version: 21
+ cache: sbt
- - name: Validate JavaScript
- if: matrix.platform == 'js'
- run: sbt ++${{ matrix.scala }} validateAllJS
+ - name: sbt update
+ if: matrix.java == 'graalvm@21' && steps.setup-java-graalvm-21.outputs.cache-hit == 'false'
+ run: sbt +update
- - name: Validate Tests Native
- if: matrix.platform == 'native'
- run: sbt ++${{ matrix.scala }} testsNative/test
+ - name: Check that workflows are up to date
+ run: sbt githubWorkflowCheck
- - name: Validate Native
- if: matrix.platform == 'native'
- run: sbt ++${{ matrix.scala }} native/test
+ - name: Check headers and formatting
+ if: matrix.java == 'temurin@8' && matrix.os == 'ubuntu-22.04'
+ run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' headerCheckAll scalafmtCheckAll 'project /' scalafmtSbtCheck
- - name: Validate Kernel Laws Native
- if: matrix.platform == 'native'
- run: sbt ++${{ matrix.scala }} kernelLawsNative/test
+ - name: nativeLink
+ if: matrix.project == 'catsNative'
+ run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' Test/nativeLink
- - name: Validate Free Native
- if: matrix.platform == 'native'
- run: sbt ++${{ matrix.scala }} freeNative/test
+ - name: scalaJSLink
+ if: matrix.project == 'catsJS'
+ run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' Test/scalaJSLinkerResult
- - name: Validate Alleycats Tests Native
- if: matrix.platform == 'native'
- run: sbt ++${{ matrix.scala }} alleycatsTestsNative/test
+ - name: Test
+ run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' test
- - name: Validate Algebra Laws Native
- if: matrix.platform == 'native'
- run: sbt ++${{ matrix.scala }} algebraLawsNative/test
+ - name: Check binary compatibility
+ if: matrix.java == 'temurin@8' && matrix.os == 'ubuntu-22.04'
+ run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' mimaReportBinaryIssues
- - name: Validate JVM (scala 2)
- if: matrix.platform == 'jvm' && (matrix.scala != '3.0.2')
- run: sbt ++${{ matrix.scala }} buildJVM bench/test
+ - name: Generate API documentation
+ if: matrix.java == 'temurin@8' && matrix.os == 'ubuntu-22.04'
+ run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' doc
- - name: Validate JVM (scala 3)
- if: matrix.platform == 'jvm' && (matrix.scala == '3.0.2')
- run: sbt ++${{ matrix.scala }} buildJVM bench/test
+ - name: Make target directories
+ if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
+ run: mkdir -p algebra-laws/jvm/target free/.js/target testkit/.native/target testkit/.js/target unidocs/target core/.native/target free/.jvm/target free/.native/target alleycats-laws/native/target laws/.native/target alleycats-core/.js/target alleycats-laws/js/target kernel/.jvm/target core/.js/target kernel/.js/target algebra-laws/native/target kernel-laws/native/target laws/.js/target core/.jvm/target alleycats-core/.native/target kernel/.native/target algebra-core/.jvm/target kernel-laws/jvm/target algebra-core/.js/target alleycats-laws/jvm/target laws/.jvm/target algebra-core/.native/target alleycats-core/.jvm/target kernel-laws/js/target testkit/.jvm/target algebra-laws/js/target project/target
- - name: Binary compatibility ${{ matrix.scala }}
- if: matrix.platform == 'jvm' && (matrix.scala != '3.0.2')
- run: sbt ++${{ matrix.scala }} clean validateBC
+ - name: Compress target directories
+ if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
+ run: tar cf targets.tar algebra-laws/jvm/target free/.js/target testkit/.native/target testkit/.js/target unidocs/target core/.native/target free/.jvm/target free/.native/target alleycats-laws/native/target laws/.native/target alleycats-core/.js/target alleycats-laws/js/target kernel/.jvm/target core/.js/target kernel/.js/target algebra-laws/native/target kernel-laws/native/target laws/.js/target core/.jvm/target alleycats-core/.native/target kernel/.native/target algebra-core/.jvm/target kernel-laws/jvm/target algebra-core/.js/target alleycats-laws/jvm/target laws/.jvm/target algebra-core/.native/target alleycats-core/.jvm/target kernel-laws/js/target testkit/.jvm/target algebra-laws/js/target project/target
- scalafix:
- name: Scalafix
+ - name: Upload target directories
+ if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
+ uses: actions/upload-artifact@v4
+ with:
+ name: target-${{ matrix.os }}-${{ matrix.java }}-${{ matrix.scala }}-${{ matrix.project }}
+ path: targets.tar
+
+ publish:
+ name: Publish Artifacts
+ needs: [build]
+ if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
strategy:
matrix:
- os: [ubuntu-latest]
- scala: [2.12.15, 2.13.7, 3.0.2]
- java: [adoptium@8]
+ os: [ubuntu-22.04]
+ java: [temurin@8]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout current branch (full)
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- - name: Setup Java and Scala
- uses: olafurpg/setup-scala@v13
+ - name: Setup sbt
+ uses: sbt/setup-sbt@v1
+
+ - name: Setup Java (temurin@8)
+ id: setup-java-temurin-8
+ if: matrix.java == 'temurin@8'
+ uses: actions/setup-java@v4
with:
- java-version: ${{ matrix.java }}
+ distribution: temurin
+ java-version: 8
+ cache: sbt
+
+ - name: sbt update
+ if: matrix.java == 'temurin@8' && steps.setup-java-temurin-8.outputs.cache-hit == 'false'
+ run: sbt +update
- - name: Cache sbt
- uses: actions/cache@v2
+ - name: Setup Java (temurin@17)
+ id: setup-java-temurin-17
+ if: matrix.java == 'temurin@17'
+ uses: actions/setup-java@v4
with:
- path: |
- ~/.sbt
- ~/.ivy2/cache
- ~/.coursier/cache/v1
- ~/.cache/coursier/v1
- ~/AppData/Local/Coursier/Cache/v1
- ~/Library/Caches/Coursier/v1
- key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }}
+ distribution: temurin
+ java-version: 17
+ cache: sbt
- - name: Scalafix tests
+ - name: sbt update
+ if: matrix.java == 'temurin@17' && steps.setup-java-temurin-17.outputs.cache-hit == 'false'
+ run: sbt +update
+
+ - name: Setup Java (graalvm@21)
+ id: setup-java-graalvm-21
+ if: matrix.java == 'graalvm@21'
+ uses: actions/setup-java@v4
+ with:
+ distribution: graalvm
+ java-version: 21
+ cache: sbt
+
+ - name: sbt update
+ if: matrix.java == 'graalvm@21' && steps.setup-java-graalvm-21.outputs.cache-hit == 'false'
+ run: sbt +update
+
+ - name: Download target directories (2.12, catsNative)
+ uses: actions/download-artifact@v4
+ with:
+ name: target-${{ matrix.os }}-${{ matrix.java }}-2.12-catsNative
+
+ - name: Inflate target directories (2.12, catsNative)
run: |
- cd scalafix
- sbt test
+ tar xf targets.tar
+ rm targets.tar
+
+ - name: Download target directories (2.12, catsJS)
+ uses: actions/download-artifact@v4
+ with:
+ name: target-${{ matrix.os }}-${{ matrix.java }}-2.12-catsJS
+
+ - name: Inflate target directories (2.12, catsJS)
+ run: |
+ tar xf targets.tar
+ rm targets.tar
+
+ - name: Download target directories (2.12, catsJVM)
+ uses: actions/download-artifact@v4
+ with:
+ name: target-${{ matrix.os }}-${{ matrix.java }}-2.12-catsJVM
+
+ - name: Inflate target directories (2.12, catsJVM)
+ run: |
+ tar xf targets.tar
+ rm targets.tar
+
+ - name: Download target directories (2.13, catsNative)
+ uses: actions/download-artifact@v4
+ with:
+ name: target-${{ matrix.os }}-${{ matrix.java }}-2.13-catsNative
+
+ - name: Inflate target directories (2.13, catsNative)
+ run: |
+ tar xf targets.tar
+ rm targets.tar
+
+ - name: Download target directories (2.13, catsJS)
+ uses: actions/download-artifact@v4
+ with:
+ name: target-${{ matrix.os }}-${{ matrix.java }}-2.13-catsJS
+
+ - name: Inflate target directories (2.13, catsJS)
+ run: |
+ tar xf targets.tar
+ rm targets.tar
+
+ - name: Download target directories (2.13, catsJVM)
+ uses: actions/download-artifact@v4
+ with:
+ name: target-${{ matrix.os }}-${{ matrix.java }}-2.13-catsJVM
+
+ - name: Inflate target directories (2.13, catsJVM)
+ run: |
+ tar xf targets.tar
+ rm targets.tar
+
+ - name: Download target directories (3, catsNative)
+ uses: actions/download-artifact@v4
+ with:
+ name: target-${{ matrix.os }}-${{ matrix.java }}-3-catsNative
+
+ - name: Inflate target directories (3, catsNative)
+ run: |
+ tar xf targets.tar
+ rm targets.tar
+
+ - name: Download target directories (3, catsJS)
+ uses: actions/download-artifact@v4
+ with:
+ name: target-${{ matrix.os }}-${{ matrix.java }}-3-catsJS
+
+ - name: Inflate target directories (3, catsJS)
+ run: |
+ tar xf targets.tar
+ rm targets.tar
+
+ - name: Download target directories (3, catsJVM)
+ uses: actions/download-artifact@v4
+ with:
+ name: target-${{ matrix.os }}-${{ matrix.java }}-3-catsJVM
- linting:
- name: Linting
+ - name: Inflate target directories (3, catsJVM)
+ run: |
+ tar xf targets.tar
+ rm targets.tar
+
+ - name: Import signing key
+ if: env.PGP_SECRET != '' && env.PGP_PASSPHRASE == ''
+ env:
+ PGP_SECRET: ${{ secrets.PGP_SECRET }}
+ PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
+ run: echo $PGP_SECRET | base64 -d -i - | gpg --import
+
+ - name: Import signing key and strip passphrase
+ if: env.PGP_SECRET != '' && env.PGP_PASSPHRASE != ''
+ env:
+ PGP_SECRET: ${{ secrets.PGP_SECRET }}
+ PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
+ run: |
+ echo "$PGP_SECRET" | base64 -d -i - > /tmp/signing-key.gpg
+ echo "$PGP_PASSPHRASE" | gpg --pinentry-mode loopback --passphrase-fd 0 --import /tmp/signing-key.gpg
+ (echo "$PGP_PASSPHRASE"; echo; echo) | gpg --command-fd 0 --pinentry-mode loopback --change-passphrase $(gpg --list-secret-keys --with-colons 2> /dev/null | grep '^sec:' | cut --delimiter ':' --fields 5 | tail -n 1)
+
+ - name: Publish
+ env:
+ SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
+ SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
+ SONATYPE_CREDENTIAL_HOST: ${{ secrets.SONATYPE_CREDENTIAL_HOST }}
+ run: sbt tlCiRelease
+
+ dependency-submission:
+ name: Submit Dependencies
+ if: github.event.repository.fork == false && github.event_name != 'pull_request'
strategy:
matrix:
- os: [ubuntu-latest]
- scala: [2.12.15, 2.13.7, 3.0.2]
- java: [adoptium@8]
+ os: [ubuntu-22.04]
+ java: [temurin@8]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout current branch (full)
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- - name: Setup Java and Scala
- uses: olafurpg/setup-scala@v13
+ - name: Setup sbt
+ uses: sbt/setup-sbt@v1
+
+ - name: Setup Java (temurin@8)
+ id: setup-java-temurin-8
+ if: matrix.java == 'temurin@8'
+ uses: actions/setup-java@v4
with:
- java-version: ${{ matrix.java }}
+ distribution: temurin
+ java-version: 8
+ cache: sbt
- - name: Cache sbt
- uses: actions/cache@v2
+ - name: sbt update
+ if: matrix.java == 'temurin@8' && steps.setup-java-temurin-8.outputs.cache-hit == 'false'
+ run: sbt +update
+
+ - name: Setup Java (temurin@17)
+ id: setup-java-temurin-17
+ if: matrix.java == 'temurin@17'
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 17
+ cache: sbt
+
+ - name: sbt update
+ if: matrix.java == 'temurin@17' && steps.setup-java-temurin-17.outputs.cache-hit == 'false'
+ run: sbt +update
+
+ - name: Setup Java (graalvm@21)
+ id: setup-java-graalvm-21
+ if: matrix.java == 'graalvm@21'
+ uses: actions/setup-java@v4
with:
- path: |
- ~/.sbt
- ~/.ivy2/cache
- ~/.coursier/cache/v1
- ~/.cache/coursier/v1
- ~/AppData/Local/Coursier/Cache/v1
- ~/Library/Caches/Coursier/v1
- key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }}
+ distribution: graalvm
+ java-version: 21
+ cache: sbt
- - name: Check formatting
- if: (matrix.scala != '3.0.2')
- run: sbt ++${{ matrix.scala }} fmtCheck
+ - name: sbt update
+ if: matrix.java == 'graalvm@21' && steps.setup-java-graalvm-21.outputs.cache-hit == 'false'
+ run: sbt +update
- microsite:
- name: Microsite
+ - name: Submit Dependencies
+ uses: scalacenter/sbt-dependency-submission@v2
+ with:
+ modules-ignore: catsnative_2.12 catsnative_2.13 catsnative_3 docs_2.12 docs_2.13 docs_3 cats-tests_sjs1_2.12 cats-tests_sjs1_2.13 cats-tests_sjs1_3 cats-tests_2.12 cats-tests_2.13 cats-tests_3 catsjs_2.12 catsjs_2.13 catsjs_3 catsjvm_2.12 catsjvm_2.13 catsjvm_3 bincompattest_2.12 bincompattest_2.13 bincompattest_3 cats-tests_native0.5_2.12 cats-tests_native0.5_2.13 cats-tests_native0.5_3 cats-bench_2.12 cats-bench_2.13 cats-bench_3
+ configs-ignore: test scala-tool scala-doc-tool test-internal
+
+ validate-steward:
+ name: Validate Steward Config
strategy:
matrix:
- os: [ubuntu-latest]
- scala: [2.12.15]
- java: [adoptium@8]
+ os: [ubuntu-22.04]
+ java: [temurin@11]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - name: Checkout current branch (fast)
+ uses: actions/checkout@v4
+
+ - name: Setup Java (temurin@11)
+ id: setup-java-temurin-11
+ if: matrix.java == 'temurin@11'
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 11
+
+ - uses: coursier/setup-action@v1
+ with:
+ apps: scala-steward
+
+ - run: scala-steward validate-repo-config .scala-steward.conf
+
+ site:
+ name: Generate Site
+ strategy:
+ matrix:
+ os: [ubuntu-22.04]
+ java: [temurin@17]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout current branch (full)
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- - name: Setup Java and Scala
- uses: olafurpg/setup-scala@v13
+ - name: Setup sbt
+ uses: sbt/setup-sbt@v1
+
+ - name: Setup Java (temurin@8)
+ id: setup-java-temurin-8
+ if: matrix.java == 'temurin@8'
+ uses: actions/setup-java@v4
with:
- java-version: ${{ matrix.java }}
+ distribution: temurin
+ java-version: 8
+ cache: sbt
- - name: Cache sbt
- uses: actions/cache@v2
+ - name: sbt update
+ if: matrix.java == 'temurin@8' && steps.setup-java-temurin-8.outputs.cache-hit == 'false'
+ run: sbt +update
+
+ - name: Setup Java (temurin@17)
+ id: setup-java-temurin-17
+ if: matrix.java == 'temurin@17'
+ uses: actions/setup-java@v4
with:
- path: |
- ~/.sbt
- ~/.ivy2/cache
- ~/.coursier/cache/v1
- ~/.cache/coursier/v1
- ~/AppData/Local/Coursier/Cache/v1
- ~/Library/Caches/Coursier/v1
- key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }}
+ distribution: temurin
+ java-version: 17
+ cache: sbt
+
+ - name: sbt update
+ if: matrix.java == 'temurin@17' && steps.setup-java-temurin-17.outputs.cache-hit == 'false'
+ run: sbt +update
- - name: Setup Ruby
- uses: ruby/setup-ruby@v1
+ - name: Setup Java (graalvm@21)
+ id: setup-java-graalvm-21
+ if: matrix.java == 'graalvm@21'
+ uses: actions/setup-java@v4
with:
- ruby-version: 2.7
+ distribution: graalvm
+ java-version: 21
+ cache: sbt
+
+ - name: sbt update
+ if: matrix.java == 'graalvm@21' && steps.setup-java-graalvm-21.outputs.cache-hit == 'false'
+ run: sbt +update
- - name: Setup Jekyll
- run: gem install jekyll -v 4.0.0
+ - name: Generate site
+ run: sbt docs/tlSite
- - name: Build the microsite
- run: sbt ++${{ matrix.scala }} docs/makeMicrosite
+ - name: Publish site
+ if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
+ uses: peaceiris/actions-gh-pages@v4.0.0
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: site/target/docs/site
+ keep_files: true
+
+ scalafix:
+ name: Scalafix
+ strategy:
+ matrix:
+ os: [ubuntu-22.04]
+ java: [temurin@8]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - name: Checkout current branch (full)
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Setup sbt
+ uses: sbt/setup-sbt@v1
+
+ - name: Setup Java (temurin@8)
+ id: setup-java-temurin-8
+ if: matrix.java == 'temurin@8'
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 8
+ cache: sbt
+
+ - name: sbt update
+ if: matrix.java == 'temurin@8' && steps.setup-java-temurin-8.outputs.cache-hit == 'false'
+ run: sbt +update
+
+ - name: Setup Java (temurin@17)
+ id: setup-java-temurin-17
+ if: matrix.java == 'temurin@17'
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 17
+ cache: sbt
+
+ - name: sbt update
+ if: matrix.java == 'temurin@17' && steps.setup-java-temurin-17.outputs.cache-hit == 'false'
+ run: sbt +update
+
+ - name: Setup Java (graalvm@21)
+ id: setup-java-graalvm-21
+ if: matrix.java == 'graalvm@21'
+ uses: actions/setup-java@v4
+ with:
+ distribution: graalvm
+ java-version: 21
+ cache: sbt
+
+ - name: sbt update
+ if: matrix.java == 'graalvm@21' && steps.setup-java-graalvm-21.outputs.cache-hit == 'false'
+ run: sbt +update
+
+ - name: Scalafix tests
+ run: |
+ cd scalafix
+ sbt test
diff --git a/.jvmopts b/.jvmopts
index afbee1f086..330e2416c8 100644
--- a/.jvmopts
+++ b/.jvmopts
@@ -1,6 +1,9 @@
-Dfile.encoding=UTF8
--Xms1G
--Xmx5G
--XX:ReservedCodeCacheSize=500M
--XX:+TieredCompilation
+-Xms2G
+-Xmx8G
+-Xss4m
+-XX:ReservedCodeCacheSize=512m
+-XX:MaxMetaspaceSize=512M
-XX:+UseParallelGC
+-XX:+TieredCompilation
+-XX:+UseAdaptiveSizePolicy
diff --git a/.scala-steward.conf b/.scala-steward.conf
new file mode 100644
index 0000000000..0223c57f0a
--- /dev/null
+++ b/.scala-steward.conf
@@ -0,0 +1,4 @@
+updates.ignore = [
+ { groupId = "org.typelevel", artifactId = "cats-core" },
+ { groupId = "co.fs2", artifactId = "fs2-core" }
+]
diff --git a/.scalafix.conf b/.scalafix.conf
deleted file mode 100644
index d26fd2b0a5..0000000000
--- a/.scalafix.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-rules = [
- AddSerializable
- AddImplicitNotFound
- TypeClassSupport
-]
-
-TypeClassSupport.opsObjectDeprecation = {
- message = "Use cats.syntax object imports"
- since = "2.2.0"
-}
diff --git a/.scalafmt.conf b/.scalafmt.conf
index b4e5f13cd9..479f53f35f 100644
--- a/.scalafmt.conf
+++ b/.scalafmt.conf
@@ -1,4 +1,4 @@
-version=3.1.2
+version=3.8.5
align.openParenCallSite = true
align.openParenDefnSite = true
maxColumn = 120
@@ -19,10 +19,15 @@ fileOverride {
"glob:**/src/{main,test}/scala-2.12/**" {
runner.dialect = scala212source3
}
- "glob:**/src/{main,test}/scala-3.x/**" {
+ "glob:**/src/{main,test}/scala-3/**" {
runner.dialect = scala3
}
}
project.excludeFilters = [
"scalafix/*"
]
+rewrite.scala3.convertToNewSyntax = true
+runner.dialectOverride.allowSignificantIndentation = false
+runner.dialectOverride.allowAsForImportRename = false
+runner.dialectOverride.allowStarWildcardImport = false
+runner.dialectOverride.allowPostfixStarVarargSplices = false
diff --git a/ADOPTERS.md b/ADOPTERS.md
new file mode 100644
index 0000000000..7145a850b2
--- /dev/null
+++ b/ADOPTERS.md
@@ -0,0 +1,126 @@
+# Adopters
+
+Here is a (non-exhaustive) list of companies that use Cats in production.
+Don't see yours? [You can add it in a PR!](https://github.com/typelevel/cats/edit/main/ADOPTERS.md)
+And if you can, consider [supporting us](https://opencollective.com/typelevel).
+
+- [47 Degrees](https://www.47deg.com)
+- [Abacus Protocol](https://abacusprotocol.com)
+- [Adobe (CCA team)](https://experienceleague.adobe.com/docs/analytics-platform/using/cja-connections/cca/overview.html?lang=en)
+- [Anduin Transactions](https://anduintransact.com)
+- [Apple Inc. (FEAR team)](https://news.ycombinator.com/item?id=16969118)
+- [AutoScout24](https://www.autoscout24.com)
+- [AvantStay](https://avantstay.com/)
+- [Avast](https://avast.com)
+- [Azavea](https://www.azavea.com/)
+- [BabylonHealth](https://www.babylonhealth.com/)
+- [Banno Group inside of Jack Henry & Associates](https://banno.com/)
+- [Basefarm](https://basefarm.com/)
+- [Blue Insight Digital](https://blueinsight.digital)
+- [buildo](https://buildo.io)
+- [BUX](https://getbux.com/)
+- [Chartboost](https://www.chartboost.com/)
+- [ClearScore](https://clearscore.com/)
+- [Cleverbase](https://cleverbase.com/en/)
+- [Codacy](https://www.codacy.com/)
+- [Code Dx](https://codedx.com/)
+- [Codecentric](https://codecentric.de)
+- [Cognite](https://www.cognite.com)
+- [Colisweb](https://www.colisweb.com/)
+- [CompStak](https://compstak.com)
+- [Coya](https://coya.com/)
+- [Criteo](https://www.criteo.com/)
+- [Datum Brain](https://datumbrain.com/)
+- [Disney](https://disney.com/)
+- [Dripower LTD](https://zd.drip.im)
+- [DriveTribe](https://drivetribe.com/)
+- [Dwolla](https://dwolla.com/)
+- [e.near](http://enear.co)
+- [E.ON](https://eon.com)
+- [Earnest](https://www.earnest.com)
+- [eBay Inc.](https://www.ebay.com)
+- [Eloquentix](https://eloquentix.com)
+- [eSailors](https://www.esailors.de)
+- [Etsy](https://etsy.com)
+- [Evolution Gaming](https://www.evolutiongaming.com/)
+- [Evotor Marketplace](https://market.evotor.ru/)
+- [Exelonix](https://exelonix.com/)
+- [formation.ai](https://formation.ai)
+- [Free2Move](https://free2move.com)
+- [Gemini Observatory](https://www.gemini.edu)
+- [HelloSoda](https://hellosoda.com)
+- [HiFi](https://hi.fi)
+- [HomeAway](https://www.homeaway.com)
+- [Hootsuite Inc.](https://hootsuite.com/)
+- [iHeartRadio](https://iheart.com)
+- [ImmobilienScout24](https://www.immobilienscout24.de/)
+- [Immozentral](https://www.immozentral.com/)
+- [ING Bank](https://www.ing.com)
+- [Inner Product](https://inner-product.com)
+- [innFactory GmbH](https://www.innfactory.de/)
+- [Intent HQ](https://www.intenthq.com/)
+- [iofod](https://www.iofod.com/)
+- [Iterators](https://www.iteratorshq.com/)
+- [ITV](https://www.itv.com/)
+- [Kaluza](https://www.kaluza.com)
+- [Lightform](https://lightform.com/)
+- [Lookout](https://www.lookout.com)
+- [Medidata](https://www.medidata.com/)
+- [Merit](https://merits.com)
+- [Metacommerce](https://www.metacommerce.ru)
+- [MYOB](https://www.myob.com)
+- [NCR Edinburgh](https://ncredinburgh.com/)
+- [Netflix](https://jobs.netflix.com)
+- [NetworkedAssets](https://www.networkedassets.com/)
+- [Nezasa](https://www.nezasa.com)
+- [Nirovision](https://www.nirovision.com)
+- [Ocado Technology](https://ocadotechnology.com)
+- [On Air Entertainment](https://onairentertainment.com/)
+- [OVO Energy](https://ovoenergy.com)
+- [Packlink](https://packlink.com/)
+- [Permutive](https://permutive.com/)
+- [PITS Globale Datenrettungsdienste](https://www.pitsdatenrettung.de/)
+- [Precog](https://precog.com)
+- [Raiffeisenbank Russia](https://www.raiffeisen.ru/)
+- [Rakuten](https://www.rakuten.com)
+- [RBC Capital Markets](https://www.rbccm.com)
+- [REA Group](https://www.realestate.com.au/)
+- [Reality Games](https://wearerealitygames.com)
+- [Revonte](https://revonte.com)
+- [Rewards Network](https://rewardsnetwork.com)
+- [RMS](https://www.rms.com/)
+- [Rudder](https://rudder.io)
+- [Scala Center](https://scala.epfl.ch)
+- [Scalac](https://scalac.io)
+- [SecurityScorecard](https://securityscorecard.io/)
+- [SEEK Limited](https://www.seek.com.au/)
+- [Snowplow Analytics](https://snowplowanalytics.com/)
+- [SoftwareMill](https://softwaremill.com)
+- [Spiceworks](https://www.spiceworks.com/)
+- [Spotahome](https://spotahome.com)
+- [Spotify](https://www.spotify.com)
+- [SpotX](https://www.spotx.tv/)
+- [SpringerNature](https://www.springernature.com)
+- [SRF](https://www.srf.ch)
+- [Standard Chartered](https://www.sc.com)
+- [Stripe](https://stripe.com)
+- [SWCoE at Philips](https://www.philips.com/)
+- [SWOP](https://swop.cx/)
+- [Tapad](https://www.tapad.com/)
+- [Tecsisa](https://www.tecsisa.com)
+- [Teikametrics](http://teikametrics.com)
+- [Tenable](https://www.tenable.com)
+- [The Guardian](https://www.theguardian.com)
+- [Tinkoff](https://tinkoff.ru)
+- [Tranzzo](https://tranzzo.com)
+- [Underscore Consulting](https://underscore.io/)
+- [vidIQ](https://vidiq.com/)
+- [Waves Platform](https://wavesplatform.com/)
+- [Wegtam GmbH](https://www.wegtam.com)
+- [Wejo](https://www.wejo.com/)
+- [WeWork](https://www.wework.com)
+- [Wix.com](https://www.wix.com)
+- [Wolt](https://wolt.com/)
+- [XITE](https://xite.com/)
+- [Zalando](https://zalando.com)
+- [Zendesk](https://www.zendesk.com)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c527590dae..a87878cacd 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -24,7 +24,7 @@ skip these steps and jump straight to submitting a pull request.
1. [Find something that belongs in cats](#find-something-that-belongs-in-cats)
2. [Let us know you are working on it](#let-us-know-you-are-working-on-it)
- 3. [Build the project](#build-project)
+ 3. [Build the project](#build-the-project)
4. [Implement your contribution](#write-code)
5. [Write tests](#write-tests)
6. [Write documentation](#contributing-documentation)
@@ -46,7 +46,7 @@ pull request. The preferred ways to do that are to either:
* [create a GitHub issue](https://github.com/typelevel/cats/issues/new)
describing your idea.
- * get feedback in the [cats Gitter room](https://gitter.im/typelevel/cats).
+ * get feedback in the [Typelevel Discord](https://discord.gg/XF3CXcMzqD)
Things that belong in Cats generally have the following characteristics:
@@ -96,7 +96,7 @@ git clone git@github.com:typelevel/cats.git
```
To build Cats you should have
-[sbt](http://www.scala-sbt.org/0.13/tutorial/Setup.html) and [Node.js](https://nodejs.org/)
+[sbt](https://www.scala-sbt.org/1.x/docs/Setup.html) and [Node.js](https://nodejs.org/)
installed. If you'd like, you can use the [Nix Cats development environment](#nix-cats-development-environment).
Run `sbt`, and then use any of the following commands:
@@ -151,11 +151,11 @@ for law checking, and imports all syntax and standard instances for convenience.
[Discipline](https://github.com/typelevel/discipline), is the name of the test and will be output to the
console as part of the test execution. By convention:
- When checking laws, this parameter generally takes a form that describes the data type being tested.
- For example the name *"Validated[String, Int]"* might be used when testing a type class instance
+ For example the name `"Validated[String, Int]"` might be used when testing a type class instance
that the `Validated` data type supports.
- An exception to this is serializability tests, where the type class name is also included in the name.
For example, in the case of `Validated`, the serializability test would take the form,
- *"Applicative[Validated[String, Int]]"*, to indicate that this test is verifying that the `Applicative`
+ `"Applicative[Validated[String, Int]]"`, to indicate that this test is verifying that the `Applicative`
type class instance for the `Validated` data type is serializable.
- This convention helps to ensure clear and easy to understand output, with minimal duplication in the output.
- It is also a goal that, for every combination of data type and supported type class instance:
@@ -187,32 +187,15 @@ As a side note, the latter command uses [sbt-mima](https://github.com/lightbend/
### source for the documentation
The documentation for this website is stored alongside the source, in the [docs subproject](https://github.com/typelevel/cats/tree/main/docs).
-* The source for the tut compiled pages is in `docs/src/main/mdoc`
-* The menu structure for these pages is in `docs/src/main/resources/microsite/data/menu.yml`
-
### Generating the Site
-run `sbt docs/makeMicrosite`
-
-### Previewing the site
-
-1. Install jekyll locally. Depending on your platform, you might do this with:
-
- `yum install jekyll`
+The command is: `sbt docs/tlSite`
- `apt-get install ruby-full; gem install jekyll`
+We suggest checking the CI's workflow to discover any changes at [CI site job](https://github.com/typelevel/cats/blob/v2.9.0/.github/workflows/ci.yml#L418).
- `gem install jekyll`
-
- Or just dropping into a `nix-shell` if you are using the [Nix Cats development environment](#nix-cats-development-environment).
-
-2. In a shell, navigate to the generated site directory in `cats-docs/target/site`
-
-3. Start jekyll with `jekyll serve -b /cats`
-
-4. Navigate to http://localhost:4000/cats/ in your browser
+### Previewing the site
-5. Make changes to your site, and run `sbt docs/makeMicrosite` to regenerate the site. The changes should be reflected as soon as you run `makeMicrosite`.
+Run `docs/tlSitePreview` in the sbt console. This will start a preview server at http://localhost:4242/ that will automatically refresh as you make edits.
### Compiler verified documentation
@@ -251,8 +234,8 @@ the contribution process for the cats project.
It may take a while to familiarize yourself with this document, but if
we are doing our job right, you shouldn't have to spend months poring
-over the project source code or lurking the
-[Gitter room](https://gitter.im/typelevel/cats) before you feel comfortable
+over the project source code or lurking on Discord
+before you feel comfortable
contributing. In fact, if you encounter any confusion or frustration
during the contribution process, please create a GitHub issue and
we'll do our best to improve the process.
@@ -260,8 +243,8 @@ we'll do our best to improve the process.
## Getting in touch
Discussion around Cats is currently happening in the
-[Gitter channel](https://gitter.im/typelevel/cats) as well as on Github
-issue and PR pages.
+[Typelevel Discord](https://discord.gg/XF3CXcMzqD)
+as well as on GitHub issue and PR pages.
Feel free to open an issue if you notice a bug, have an idea for a
feature, or have a question about the code. Pull requests are also
@@ -269,8 +252,7 @@ gladly accepted.
People are expected to follow the
[Scala Code of Conduct](https://www.scala-lang.org/conduct/) when
-discussing Cats on the Github page, Gitter channel, or other
-venues.
+discussing Cats on GitHub, Discord, or other venues.
We hope that our community will be respectful, helpful, and kind. If
you find yourself embroiled in a situation that becomes heated, or
diff --git a/COPYING b/COPYING
index 6e5add81f8..d5783383b2 100644
--- a/COPYING
+++ b/COPYING
@@ -5,10 +5,10 @@ this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
+so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@@ -16,7 +16,7 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+SOFTWARE.
------
@@ -47,3 +47,209 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+------
+
+Code in Cats is derived in part from the Scala standard library. The Scala license follows:
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/DESIGN.md b/DESIGN.md
index 05e27ddcb4..d023c8696f 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -7,7 +7,6 @@ ensure correctness.
Cats will be designed to use modern *best practices*:
- * [simulacrum](https://github.com/typelevel/simulacrum) for minimizing type class boilerplate
* [machinist](https://github.com/typelevel/machinist) for optimizing implicit operators
* [scalacheck](http://scalacheck.org) for property-based testing
* [discipline](https://github.com/typelevel/discipline) for encoding and testing laws
@@ -36,11 +35,11 @@ Cats provides the following modules:
* `core`: Definitions for widely-used type classes and data types.
* `laws`: The encoded laws for type classes defined in `core`, exported to assist third-party testing.
- * `kernel`: Definitions for the basic algebraic type classes
+ * `kernel`: Definitions for the basic algebraic type classes
* `kernel-laws`: The encoded laws for type classes defined in `kernel`, exported to assist third-party testing.
* `free`: Free structures such as the free monad, and supporting type classes.
* `tests`: Verifies the laws, and runs any other tests. Not published.
- * `bench`: Benchmarking suites. Not published.
+ * `bench`: Benchmarking suites. Not published.
As the type class families grow, it's possible that additional modules
will be added as well. Modules which depend on other libraries
diff --git a/PROCESS.md b/PROCESS.md
index 1b933dc98c..189e78690b 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -21,7 +21,7 @@ one sign-off is required (although for major edits waiting for two
For serious emergencies or work on the build which can't easily be
reviewed or tested, pushing directly to main may be OK (but is
definitely not encouraged). In these cases it's best to comment in
-Gitter or elsewhere about what happened and what was done.
+Discord or elsewhere about what happened and what was done.
### Versioning
diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md
deleted file mode 100644
index d11bc1346c..0000000000
--- a/PULL_REQUEST_TEMPLATE.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Thank you for contributing to Cats!
-
-This is a kind reminder to run `sbt +prePR` and commit the changed files, if any, before submitting.
-
-
diff --git a/README.md b/README.md
index aa741a5ea4..1112f5a345 100644
--- a/README.md
+++ b/README.md
@@ -1,38 +1,33 @@
-
-### Community Announcements
-
-* **Oct 31 2020** [Cats 2.3.0-M1 is released](https://github.com/typelevel/cats/releases/tag/v2.3.0-M1) with Dotty supported
-* **Sept 3 2020** [Cats 2.2.0 is released](https://github.com/typelevel/cats/releases/tag/v2.2.0)
-* **Dec 18 2019** [Cats 2.1.0 is released](https://github.com/typelevel/cats/releases/tag/v2.1.0)
-* **Sep 9 2019** [Cats 2.0.0 is released](https://github.com/typelevel/cats/releases/tag/v2.0.0)
-* **Jun 3 2019** [Cats 1.6.1 is released](https://github.com/typelevel/cats/releases/tag/v1.6.1) with backported bug fixes
-* **Apr 26 2019** [We launched a sustainability program](https://typelevel.org/blog/2019/04/24/typelevel-sustainability-program-announcement.html). Please consider supporting us.
-
## Cats
-
+
[](https://index.scala-lang.org/typelevel/cats/cats-core) 
-[](https://opencollective.com/typelevel) [](https://gitter.im/typelevel/cats)
-[](https://discord.gg/hWd4eS244g)
+[](https://opencollective.com/typelevel)
+[](https://discord.gg/XF3CXcMzqD)
### Overview
Cats is a library which provides abstractions for functional programming in the [Scala programming language](https://scala-lang.org).
-The name is a playful shortening of the word *category*.
Scala supports both object-oriented and functional programming, and this is reflected in the hybrid approach of the
-standard library. Cats strives to provide functional programming abstractions that are core, [binary compatible](http://typelevel.org/cats/#binary-compatibility-and-versioning), [modular](http://typelevel.org/cats/motivations#modularity), [approachable](http://typelevel.org/cats/motivations#approachability) and [efficient](http://typelevel.org//cats/motivations#efficiency). A broader goal of Cats is to provide a foundation for an [ecosystem of pure, typeful libraries](https://typelevel.org/cats/#ecosystem) to support functional programming in Scala applications.
+standard library. Cats strives to provide functional programming abstractions that are core, [binary compatible](#binary-compatibility-and-versioning), [modular](https://typelevel.org/cats/motivations.html#modularity), [approachable](https://typelevel.org/cats/motivations.html#approachability) and [efficient](https://typelevel.org/cats/motivations.html#efficiency). A broader goal of Cats is to provide a foundation for an [ecosystem of pure, typeful libraries](https://typelevel.org/cats/typelevelEcosystem.html) to support functional programming in Scala applications.
+
+For more detail about Cats' motivations, go [here](https://typelevel.org/cats/motivations.html).
+
+### Why "cats"?
-For more detail about Cats' motivations, go [here](http://typelevel.org/cats/motivations).
+The name is a playful shortening of the word *category*, from "[category theory](https://en.wikipedia.org/wiki/Category_theory)".
+
+Regardless, you do not need to know anything about category theory to use Cats.
## Contributors
### Code Contributors
This project exists thanks to [all the people who contribute](https://github.com/typelevel/cats/graphs/contributors). We welcome contributions to Cats and would love for you to help build
-Cats. See our [contributor guide](https://typelevel.org/cats/contributing.html) for more
-information about how you can get involved as a developer. If you are looking for something to start with, [here is a beginner friendly list](https://github.com/typelevel/cats/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
+Cats. See our [contributor guide](CONTRIBUTING.md) for more
+information about how you can get involved as a developer. If you are looking for something to start with, [here is a beginner friendly list](https://github.com/typelevel/cats/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
### Financial Contributors
@@ -41,31 +36,31 @@ information about how you can get involved as a developer. If you are looking fo
Platinum Sponsors
Platinum sponsorship starts at $950 USD/month.
Gold Sponsors
Gold Sponsorship starts at $420 USD/month.
Silver Sponsors
Silver Sponsorship starts at $180 USD/month.
Backers
Become a Backer with a recurring donation of just $5 USD/month.
Other contributors
We thankfully accept one-time and recurring contributions as well.
@@ -74,7 +69,7 @@ We thankfully accept one-t
Cats is available for [Scala.js](http://www.scala-js.org/) and [Scala Native](https://www.scala-native.org/), as well as the standard JVM runtime.
-Cats relies on improved type inference via the fix for [SI-2712](https://github.com/scala/bug/issues/2712), which is not enabled by default. For **Scala 2.11.9+ or 2.12** you should add the following to your `build.sbt`:
+Cats relies on improved type inference via the fix for [SI-2712](https://github.com/scala/bug/issues/2712), which is not enabled by default. For **Scala 2.12** you should add the following to your `build.sbt`:
```scala
scalacOptions += "-Ypartial-unification"
@@ -82,16 +77,10 @@ scalacOptions += "-Ypartial-unification"
(Partial unification is on by default since Scala 2.13, the compiler no longer accepts `-Ypartial-unification`)
-**Or**, if you need to support older versions of Scala you can use the [sbt-partial-unification](https://github.com/fiadliel/sbt-partial-unification#sbt-partial-unification) plugin which extends support back through **Scala 2.10.6 or later**, to add it, simply add this line to your `plugins.sbt`:
-
-```scala
-addSbtPlugin("org.lyranthe.sbt" % "partial-unification" % "1.1.2")
-```
-
And then create the Cats dependency, by adding the following to your `build.sbt`:
```scala
-libraryDependencies += "org.typelevel" %% "cats-core" % "2.3.0"
+libraryDependencies += "org.typelevel" %% "cats-core" % "2.9.0"
```
This will pull in the cats-core module. If you require some other
@@ -104,14 +93,14 @@ functionality, you can pick-and-choose from amongst these modules
* `cats-free`: Free structures such as the free monad, and supporting type classes.
* `cats-testkit`: lib for writing tests for type class instances using laws.
* `algebra`: Type classes to represent algebraic structures.
- * `alleycats-core`: Cats instances and classes which are not lawful.
-
- There are several other Cats modules that are in separate repos so that they can
- maintain independent release cycles.
-
- * [`cats-effect`](https://github.com/typelevel/cats-effect): standard `IO` type together with `Sync`, `Async` and `Effect` type classes
+ * `alleycats-core`: Cats instances and classes which are not lawful.
+
+ There are several other Cats modules that are in separate repos so that they can
+ maintain independent release cycles.
+
+ * [`cats-effect`](https://github.com/typelevel/cats-effect): standard `IO` type together with `Sync`, `Async` and `Effect` type classes
* [`cats-mtl`](https://github.com/typelevel/cats-mtl): transformer typeclasses for Cats' Monads, Applicatives and Functors.
- * [`mouse`](https://github.com/typelevel/mouse): a small companion to Cats that provides convenient syntax (aka extension methods)
+ * [`mouse`](https://github.com/typelevel/mouse): a small companion to Cats that provides convenient syntax (aka extension methods)
* [`kittens`](https://github.com/typelevel/kittens): automatic type class instance derivation for Cats and generic utility functions
* [`cats-tagless`](https://github.com/typelevel/cats-tagless): Utilities for tagless final encoded algebras
* [`cats-collections`](https://github.com/typelevel/cats-collections): Data structures which facilitate pure functional programming
@@ -125,7 +114,7 @@ Links:
1. Website: [typelevel.org/cats/](https://typelevel.org/cats/)
2. ScalaDoc: [typelevel.org/cats/api/](https://typelevel.org/cats/api/)
-3. Type classes: [typelevel.org/cats/typeclasses](https://typelevel.org/cats/typeclasses.html)
+3. Type classes: [typelevel.org/cats/typeclasses.html](https://typelevel.org/cats/typeclasses.html)
4. Data types: [typelevel.org/cats/datatypes.html](https://typelevel.org/cats/datatypes.html)
5. Algebra overview: [typelevel.org/cats/algebra.html](https://typelevel.org/cats/algebra.html)
6. Glossary: [typelevel.org/cats/nomenclature.html](https://typelevel.org/cats/nomenclature.html)
@@ -135,24 +124,15 @@ Links:
### Community
-Discussion around Cats is currently happening on Github issues, PR pages,
-two Gitter channels, and we're also trying out Discord:
-
-[Typelevel Discord](https://discord.gg/XF3CXcMzqD) has access to all of the
-Typelevel library channels as well as community channels. Please join us!
-
-[Gitter channel cats](https://gitter.im/typelevel/cats) is for general user
-questions and discussions, and
+Discussion around Cats is currently happening on GitHub issues, PR pages,
+and Discord:
-[Gitter channel cats-dev](https://gitter.im/typelevel/cats-dev)
-is dedicated for Cats development related discussions. For people who wants to
-follow closely and/or to participate in the decisions in Cats development,
-this is the room to join.
+The [Typelevel Discord](https://discord.gg/XF3CXcMzqD) has \#cats and \#cats-dev
+channels, as well as community channels such as \#beginners. Please join us!
People are expected to follow the
[Scala Code of Conduct](https://www.scala-lang.org/conduct/) when
-discussing Cats on the Github page, Gitter channel, or other
-venues.
+discussing Cats on GitHub, Discord, or other venues.
We hope that our community will be respectful, helpful, and kind. If
you find yourself embroiled in a situation that becomes heated, or
@@ -166,130 +146,44 @@ immediately so that we can support you.
### Binary compatibility and versioning
-After `1.0.0` release, we [decided](https://github.com/typelevel/cats/issues/1233)
+After `1.0.0` release, we [decided](https://github.com/typelevel/cats/issues/1233)
to use *MAJOR.MINOR.PATCH* [Semantic Versioning 2.0.0](http://semver.org/)
-going forward, which is different from the *EPOCH.MAJOR.MINOR* scheme common among
-Java and Scala libraries (including the Scala lang).
+going forward, which is different from the *EPOCH.MAJOR.MINOR* scheme common among
+Java and Scala libraries (including the Scala lang).
Cats strives to provide a solid and stable foundation for an ecosystem of
-FP libraries. Thus, we treat backward binary compatibility maintenance with a high priority.
+FP libraries. Thus, we treat backward binary compatibility maintenance with a high priority.
In semantic versioning, backward breaking change is **ONLY** allowed between *MAJOR* versions.
We will maintain backward binary compatibility between *PATCH* AND *MINOR* versions.
-For example, when we release Cats `1.1.0`, it will be backward binary compatible
-with the previous `1.0.x` versions. I.E. the new JAR will be a drop-in replacement for
+For example, when we release Cats `1.1.0`, it will be backward binary compatible
+with the previous `1.0.x` versions. I.E. the new JAR will be a drop-in replacement for
the old one. This is critical when your application has a diamond
-dependency on Cats - depending on two or more libraries that all depend on Cats.
-If one library upgrades to the new `1.1.0` Cats before the other one does, your
+dependency on Cats - depending on two or more libraries that all depend on Cats.
+If one library upgrades to the new `1.1.0` Cats before the other one does, your
application still runs thanks to this backward binary compatibility.
-Also worth noting is that according to semantic versioning,
-*MINOR* version Y (x.Y.z | x > 0) MUST be incremented
-if new, backwards compatible functionality is introduced to the public API.
+Also worth noting is that according to semantic versioning,
+*MINOR* version Y (x.Y.z | x > 0) MUST be incremented
+if new, backwards compatible functionality is introduced to the public API.
It MUST be incremented if any public API functionality is marked as deprecated.
Any binary breaking changes will require a *MAJOR* version bump, which we will be very
-cautious about. We will also consider using `organization` and package name for major
-versioning in the future. But that decision is yet to be made.
+cautious about. We will also consider using `organization` and package name for major
+versioning in the future. But that decision is yet to be made.
### Adopters
-Here's a (non-exhaustive) list of companies that use Cats in production. Don't see yours? [You can add it in a PR!](https://github.com/typelevel/cats/edit/main/README.md) And if you can, consider [supporting us](https://donorbox.org/typelevel-sustainability-program-2019?default_interval=m).
-
-- [Abacus Protocol](https://abacusprotocol.com)
-- [Adobe (CCA team)](https://experienceleague.adobe.com/docs/analytics-platform/using/cja-connections/cca/overview.html?lang=en)
-- [Anduin Transactions](https://anduintransact.com)
-- [Apple Inc. (FEAR team)](https://news.ycombinator.com/item?id=16969118)
-- [AutoScout24](https://www.autoscout24.com)
-- [AvantStay](https://avantstay.com/)
-- [Avast](https://avast.com)
-- [BabylonHealth](https://www.babylonhealth.com/)
-- [Banno Group inside of Jack Henry & Associates](https://banno.com/)
-- [Basefarm](https://basefarm.com/)
-- [buildo](https://buildo.io)
-- [Chartboost](https://www.chartboost.com/)
-- [Cleverbase](https://cleverbase.com/en/)
-- [Codacy](https://www.codacy.com/)
-- [Codecentric](https://codecentric.de)
-- [Colisweb](https://www.colisweb.com/)
-- [Coya](https://coya.com/)
-- [Datum Brain](https://datumbrain.com/)
-- [DriveTribe](https://drivetribe.com/)
-- [Dwolla](https://dwolla.com/)
-- [Earnest](https://www.earnest.com)
-- [eBay Inc.](https://www.ebay.com)
-- [Eloquentix](https://eloquentix.com)
-- [eSailors](https://www.esailors.de)
-- [Evolution Gaming](https://www.evolutiongaming.com/)
-- [Evotor Marketplace](https://market.evotor.ru/)
-- [e.near](http://enear.co)
-- [E.ON](https://eon.com)
-- [formation.ai](https://formation.ai)
-- [Free2Move](https://free2move.com)
-- [HelloSoda](https://hellosoda.com)
-- [HiFi](https://hi.fi)
-- [HomeAway](https://www.homeaway.com)
-- [Hootsuite Inc.](https://hootsuite.com/)
-- [iHeartRadio](https://iheart.com)
-- [ImmobilienScout24](https://www.immobilienscout24.de/)
-- [Immozentral](https://www.immozentral.com/)
-- [innFactory GmbH](https://www.innfactory.de/)
-- [Iterators](https://www.iteratorshq.com/)
-- [ITV](https://www.itv.com/)
-- [Lightform](https://lightform.com/)
-- [Lookout](https://www.lookout.com)
-- [Medidata](https://www.medidata.com/)
-- [Merit](https://merits.com)
-- [Metacommerce](https://www.metacommerce.ru)
-- [MYOB](https://www.myob.com)
-- [Netflix](https://jobs.netflix.com)
-- [NetworkedAssets](https://www.networkedassets.com/)
-- [Nezasa](https://www.nezasa.com)
-- [NCR Edinburgh](https://ncredinburgh.com/)
-- [Ocado Technology](https://ocadotechnology.com)
-- [Packlink](https://packlink.com/)
-- [Permutive](https://permutive.com/)
-- [Raiffeisenbank Russia](https://www.raiffeisen.ru/)
-- [Rakuten](https://www.rakuten.com)
-- [REA Group](https://www.realestate.com.au/)
-- [Reality Games](https://wearerealitygames.com)
-- [Rewards Network](https://rewardsnetwork.com)
-- [RBC Capital Markets](https://www.rbccm.com)
-- [Rudder](https://rudder.io)
-- [Scalac](https://scalac.io)
-- [Scala Center](https://scala.epfl.ch)
-- [SecurityScorecard](https://securityscorecard.io/)
-- [SEEK Limited](https://www.seek.com.au/)
-- [Snowplow Analytics](https://snowplowanalytics.com/)
-- [Spiceworks](https://www.spiceworks.com/)
-- [Spotahome](https://spotahome.com)
-- [Spotify](https://www.spotify.com)
-- [SpringerNature](https://www.springernature.com)
-- [SRF](https://www.srf.ch)
-- [Stripe](https://stripe.com)
-- [Tecsisa](https://www.tecsisa.com)
-- [Teikametrics](http://teikametrics.com)
-- [Tinkoff](https://tinkoff.ru)
-- [Tranzzo](https://tranzzo.com)
-- [The Guardian](https://www.theguardian.com)
-- [Underscore Consulting](https://underscore.io/)
-- [Waves Platform](https://wavesplatform.com/)
-- [Wegtam GmbH](https://www.wegtam.com)
-- [Wejo](https://www.wejo.com/)
-- [WeWork](https://www.wework.com)
-- [Wix.com](https://www.wix.com)
-- [Wolt](https://wolt.com/)
-- [Zalando](https://zalando.com)
-- [47 Degrees](https://www.47deg.com)
+A (non-exhaustive) list of companies that use Cats in production is featured in [ADOPTERS.md](./ADOPTERS.md). Don't see yours? [You can add it in a PR!](https://github.com/typelevel/cats/edit/main/ADOPTERS.md) And if you can, consider [supporting us](https://opencollective.com/typelevel).
### Maintainers
The current maintainers (people who can merge pull requests) are:
- * [ceedubs](https://github.com/ceedubs) Cody Allen
* [rossabaker](https://github.com/rossabaker) Ross Baker
+ * [armanbilge](https://github.com/armanbilge) Arman Bilge
* [johnynek](https://github.com/johnynek) P. Oscar Boykin
- * [travisbrown](https://github.com/travisbrown) Travis Brown
* [adelbertc](https://github.com/adelbertc) Adelbert Chang
+ * [danicheg](https://github.com/danicheg) Daniel Esik
* [LukaJCB](https://github.com/LukaJCB) Luka Jacobowitz
* [peterneyens](https://github.com/peterneyens) Peter Neyens
* [tpolecat](https://github.com/tpolecat) Rob Norris
@@ -299,9 +193,15 @@ The current maintainers (people who can merge pull requests) are:
* [milessabin](https://github.com/milessabin) Miles Sabin
* [djspiewak](https://github.com/djspiewak) Daniel Spiewak
* [fthomas](https://github.com/fthomas) Frank Thomas
+ * [satorg](https://github.com/satorg) Sergey Torgashov
* [julien-truffaut](https://github.com/julien-truffaut) Julien Truffaut
* [kailuowang](https://github.com/kailuowang) Kailuo Wang
+Retired committers include:
+
+ * [ceedubs](https://github.com/ceedubs) Cody Allen
+ * [travisbrown](https://github.com/travisbrown) Travis Brown
+
We are currently following a practice of requiring at least two
sign-offs to merge code PRs (and for large or contentious issues we may
wait for more). For typos, documentation improvements or minor build fix we
@@ -314,7 +214,7 @@ relax this to a single sign-off. More detail in the [process document](https://g
All code is available to you under the MIT license, available at
http://opensource.org/licenses/mit-license.php and also in the
-[COPYING](COPYING) file. The design is informed by many other
+[COPYING](https://github.com/typelevel/cats/blob/main/COPYING) file. The design is informed by many other
projects, in particular [Scalaz](https://github.com/scalaz/scalaz).
-Copyright the maintainers, 2015-2021.
+Copyright the maintainers, 2015-2024.
diff --git a/algebra-core/src/main/scala/algebra/Priority.scala b/algebra-core/src/main/scala/algebra/Priority.scala
index 1c5f930273..b48ab1f7a8 100644
--- a/algebra-core/src/main/scala/algebra/Priority.scala
+++ b/algebra-core/src/main/scala/algebra/Priority.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
import scala.annotation.nowarn
diff --git a/algebra-core/src/main/scala/algebra/instances/StaticMethods.scala b/algebra-core/src/main/scala/algebra/instances/StaticMethods.scala
index 02eb30d555..18f0edf5cc 100644
--- a/algebra-core/src/main/scala/algebra/instances/StaticMethods.scala
+++ b/algebra-core/src/main/scala/algebra/instances/StaticMethods.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.instances
import scala.annotation.tailrec
diff --git a/algebra-core/src/main/scala/algebra/instances/all.scala b/algebra-core/src/main/scala/algebra/instances/all.scala
index be730a79cf..953c1beec4 100644
--- a/algebra-core/src/main/scala/algebra/instances/all.scala
+++ b/algebra-core/src/main/scala/algebra/instances/all.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/array.scala b/algebra-core/src/main/scala/algebra/instances/array.scala
index 2e4a27226a..d2b451790b 100644
--- a/algebra-core/src/main/scala/algebra/instances/array.scala
+++ b/algebra-core/src/main/scala/algebra/instances/array.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/bigDecimal.scala b/algebra-core/src/main/scala/algebra/instances/bigDecimal.scala
index 89d7a6e3f2..e36e0438a7 100644
--- a/algebra-core/src/main/scala/algebra/instances/bigDecimal.scala
+++ b/algebra-core/src/main/scala/algebra/instances/bigDecimal.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/bigInt.scala b/algebra-core/src/main/scala/algebra/instances/bigInt.scala
index 3c5696319b..56aa584d4f 100644
--- a/algebra-core/src/main/scala/algebra/instances/bigInt.scala
+++ b/algebra-core/src/main/scala/algebra/instances/bigInt.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/bitSet.scala b/algebra-core/src/main/scala/algebra/instances/bitSet.scala
index a14e6a441b..b970848c56 100644
--- a/algebra-core/src/main/scala/algebra/instances/bitSet.scala
+++ b/algebra-core/src/main/scala/algebra/instances/bitSet.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/boolean.scala b/algebra-core/src/main/scala/algebra/instances/boolean.scala
index f4bf0e295a..7dd0a0e548 100644
--- a/algebra-core/src/main/scala/algebra/instances/boolean.scala
+++ b/algebra-core/src/main/scala/algebra/instances/boolean.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/byte.scala b/algebra-core/src/main/scala/algebra/instances/byte.scala
index 4e3197fe67..85f5fd924f 100644
--- a/algebra-core/src/main/scala/algebra/instances/byte.scala
+++ b/algebra-core/src/main/scala/algebra/instances/byte.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/char.scala b/algebra-core/src/main/scala/algebra/instances/char.scala
index 25701780a3..dc1515a437 100644
--- a/algebra-core/src/main/scala/algebra/instances/char.scala
+++ b/algebra-core/src/main/scala/algebra/instances/char.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/double.scala b/algebra-core/src/main/scala/algebra/instances/double.scala
index 9c59145f79..c9f1fa6656 100644
--- a/algebra-core/src/main/scala/algebra/instances/double.scala
+++ b/algebra-core/src/main/scala/algebra/instances/double.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/float.scala b/algebra-core/src/main/scala/algebra/instances/float.scala
index a8267dd7ec..80e6bcd39f 100644
--- a/algebra-core/src/main/scala/algebra/instances/float.scala
+++ b/algebra-core/src/main/scala/algebra/instances/float.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/int.scala b/algebra-core/src/main/scala/algebra/instances/int.scala
index 77762f7ac7..f9fff644d8 100644
--- a/algebra-core/src/main/scala/algebra/instances/int.scala
+++ b/algebra-core/src/main/scala/algebra/instances/int.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/list.scala b/algebra-core/src/main/scala/algebra/instances/list.scala
index 7bf52cbc81..02acc1463e 100644
--- a/algebra-core/src/main/scala/algebra/instances/list.scala
+++ b/algebra-core/src/main/scala/algebra/instances/list.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/long.scala b/algebra-core/src/main/scala/algebra/instances/long.scala
index 3c5f917b9c..0fb2061df3 100644
--- a/algebra-core/src/main/scala/algebra/instances/long.scala
+++ b/algebra-core/src/main/scala/algebra/instances/long.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/map.scala b/algebra-core/src/main/scala/algebra/instances/map.scala
index 026c51998d..fc0ca634a4 100644
--- a/algebra-core/src/main/scala/algebra/instances/map.scala
+++ b/algebra-core/src/main/scala/algebra/instances/map.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/option.scala b/algebra-core/src/main/scala/algebra/instances/option.scala
index d6db1b1e05..64203293c7 100644
--- a/algebra-core/src/main/scala/algebra/instances/option.scala
+++ b/algebra-core/src/main/scala/algebra/instances/option.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/set.scala b/algebra-core/src/main/scala/algebra/instances/set.scala
index c2eba6f151..570ebe8597 100644
--- a/algebra-core/src/main/scala/algebra/instances/set.scala
+++ b/algebra-core/src/main/scala/algebra/instances/set.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/short.scala b/algebra-core/src/main/scala/algebra/instances/short.scala
index e40f36cb53..a004493c02 100644
--- a/algebra-core/src/main/scala/algebra/instances/short.scala
+++ b/algebra-core/src/main/scala/algebra/instances/short.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/string.scala b/algebra-core/src/main/scala/algebra/instances/string.scala
index 8e9817035f..c743dcbe5b 100644
--- a/algebra-core/src/main/scala/algebra/instances/string.scala
+++ b/algebra-core/src/main/scala/algebra/instances/string.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/tuple.scala b/algebra-core/src/main/scala/algebra/instances/tuple.scala
index a73a87c67a..7a05c0aed0 100644
--- a/algebra-core/src/main/scala/algebra/instances/tuple.scala
+++ b/algebra-core/src/main/scala/algebra/instances/tuple.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/instances/unit.scala b/algebra-core/src/main/scala/algebra/instances/unit.scala
index 6ee3fcedb8..1fea97a6f3 100644
--- a/algebra-core/src/main/scala/algebra/instances/unit.scala
+++ b/algebra-core/src/main/scala/algebra/instances/unit.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package instances
diff --git a/algebra-core/src/main/scala/algebra/lattice/Bool.scala b/algebra-core/src/main/scala/algebra/lattice/Bool.scala
index a1b5dd2ff0..cae34de0cf 100644
--- a/algebra-core/src/main/scala/algebra/lattice/Bool.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/Bool.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
diff --git a/algebra-core/src/main/scala/algebra/lattice/BoundedDistributiveLattice.scala b/algebra-core/src/main/scala/algebra/lattice/BoundedDistributiveLattice.scala
index 6d3838bfb9..a439e993b2 100644
--- a/algebra-core/src/main/scala/algebra/lattice/BoundedDistributiveLattice.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/BoundedDistributiveLattice.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
diff --git a/algebra-core/src/main/scala/algebra/lattice/BoundedJoinSemilattice.scala b/algebra-core/src/main/scala/algebra/lattice/BoundedJoinSemilattice.scala
index dc8189a3f9..a6fd578964 100644
--- a/algebra-core/src/main/scala/algebra/lattice/BoundedJoinSemilattice.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/BoundedJoinSemilattice.scala
@@ -1,15 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
import scala.{specialized => sp}
-trait BoundedJoinSemilattice[@sp(Int, Long, Float, Double) A] extends Any with JoinSemilattice[A] { self =>
+trait BoundedJoinSemilattice[@sp(Int, Long, Float, Double) A] extends Any with JoinSemilattice[A] {
def zero: A
def isZero(a: A)(implicit ev: Eq[A]): Boolean = ev.eqv(a, zero)
override def joinSemilattice: BoundedSemilattice[A] =
new BoundedSemilattice[A] {
- def empty: A = self.zero
+ def empty: A = zero
def combine(x: A, y: A): A = join(x, y)
}
}
diff --git a/algebra-core/src/main/scala/algebra/lattice/BoundedLattice.scala b/algebra-core/src/main/scala/algebra/lattice/BoundedLattice.scala
index f1dab0da4a..c16e2b0a20 100644
--- a/algebra-core/src/main/scala/algebra/lattice/BoundedLattice.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/BoundedLattice.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
diff --git a/algebra-core/src/main/scala/algebra/lattice/BoundedMeetSemilattice.scala b/algebra-core/src/main/scala/algebra/lattice/BoundedMeetSemilattice.scala
index 1b2f37a6ef..23f88ffd56 100644
--- a/algebra-core/src/main/scala/algebra/lattice/BoundedMeetSemilattice.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/BoundedMeetSemilattice.scala
@@ -1,15 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
import scala.{specialized => sp}
-trait BoundedMeetSemilattice[@sp(Int, Long, Float, Double) A] extends Any with MeetSemilattice[A] { self =>
+trait BoundedMeetSemilattice[@sp(Int, Long, Float, Double) A] extends Any with MeetSemilattice[A] {
def one: A
def isOne(a: A)(implicit ev: Eq[A]): Boolean = ev.eqv(a, one)
override def meetSemilattice: BoundedSemilattice[A] =
new BoundedSemilattice[A] {
- def empty: A = self.one
+ def empty: A = one
def combine(x: A, y: A): A = meet(x, y)
}
}
diff --git a/algebra-core/src/main/scala/algebra/lattice/DeMorgan.scala b/algebra-core/src/main/scala/algebra/lattice/DeMorgan.scala
index e5b30906a5..27da092d49 100644
--- a/algebra-core/src/main/scala/algebra/lattice/DeMorgan.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/DeMorgan.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
diff --git a/algebra-core/src/main/scala/algebra/lattice/DistributiveLattice.scala b/algebra-core/src/main/scala/algebra/lattice/DistributiveLattice.scala
index c2a764d8c7..f01177f59c 100644
--- a/algebra-core/src/main/scala/algebra/lattice/DistributiveLattice.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/DistributiveLattice.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
diff --git a/algebra-core/src/main/scala/algebra/lattice/GenBool.scala b/algebra-core/src/main/scala/algebra/lattice/GenBool.scala
index a939610ef2..ce535ff167 100644
--- a/algebra-core/src/main/scala/algebra/lattice/GenBool.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/GenBool.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
diff --git a/algebra-core/src/main/scala/algebra/lattice/Heyting.scala b/algebra-core/src/main/scala/algebra/lattice/Heyting.scala
index d5dbe0c0a0..4afd255b2a 100644
--- a/algebra-core/src/main/scala/algebra/lattice/Heyting.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/Heyting.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
diff --git a/algebra-core/src/main/scala/algebra/lattice/JoinSemilattice.scala b/algebra-core/src/main/scala/algebra/lattice/JoinSemilattice.scala
index ae7c019ae5..13219a4952 100644
--- a/algebra-core/src/main/scala/algebra/lattice/JoinSemilattice.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/JoinSemilattice.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
@@ -8,13 +29,10 @@ import scala.{specialized => sp}
* operation is called "join", and which can be thought of as a least
* upper bound.
*/
-trait JoinSemilattice[@sp(Int, Long, Float, Double) A] extends Any with Serializable { self =>
+trait JoinSemilattice[@sp(Int, Long, Float, Double) A] extends Any with Serializable {
def join(lhs: A, rhs: A): A
- def joinSemilattice: Semilattice[A] =
- new Semilattice[A] {
- def combine(x: A, y: A): A = self.join(x, y)
- }
+ def joinSemilattice: Semilattice[A] = join(_, _)
def joinPartialOrder(implicit ev: Eq[A]): PartialOrder[A] =
joinSemilattice.asJoinPartialOrder
diff --git a/algebra-core/src/main/scala/algebra/lattice/Lattice.scala b/algebra-core/src/main/scala/algebra/lattice/Lattice.scala
index 040f3d66fd..f04e94c067 100644
--- a/algebra-core/src/main/scala/algebra/lattice/Lattice.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/Lattice.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
diff --git a/algebra-core/src/main/scala/algebra/lattice/Logic.scala b/algebra-core/src/main/scala/algebra/lattice/Logic.scala
index 1fd07eb8c0..b5b5380be6 100644
--- a/algebra-core/src/main/scala/algebra/lattice/Logic.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/Logic.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
diff --git a/algebra-core/src/main/scala/algebra/lattice/MeetSemilattice.scala b/algebra-core/src/main/scala/algebra/lattice/MeetSemilattice.scala
index 1dc72df29f..02063093b0 100644
--- a/algebra-core/src/main/scala/algebra/lattice/MeetSemilattice.scala
+++ b/algebra-core/src/main/scala/algebra/lattice/MeetSemilattice.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package lattice
@@ -8,13 +29,10 @@ import scala.{specialized => sp}
* operation is called "meet", and which can be thought of as a
* greatest lower bound.
*/
-trait MeetSemilattice[@sp(Int, Long, Float, Double) A] extends Any with Serializable { self =>
+trait MeetSemilattice[@sp(Int, Long, Float, Double) A] extends Any with Serializable {
def meet(lhs: A, rhs: A): A
- def meetSemilattice: Semilattice[A] =
- new Semilattice[A] {
- def combine(x: A, y: A): A = self.meet(x, y)
- }
+ def meetSemilattice: Semilattice[A] = meet(_, _)
def meetPartialOrder(implicit ev: Eq[A]): PartialOrder[A] =
meetSemilattice.asMeetPartialOrder
diff --git a/algebra-core/src/main/scala/algebra/package.scala b/algebra-core/src/main/scala/algebra/package.scala
index 0f720497ef..4a06182e41 100644
--- a/algebra-core/src/main/scala/algebra/package.scala
+++ b/algebra-core/src/main/scala/algebra/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package object algebra {
type Band[A] = cats.kernel.Band[A]
diff --git a/algebra-core/src/main/scala/algebra/ring/Additive.scala b/algebra-core/src/main/scala/algebra/ring/Additive.scala
index ef5acc7801..dba76626e1 100644
--- a/algebra-core/src/main/scala/algebra/ring/Additive.scala
+++ b/algebra-core/src/main/scala/algebra/ring/Additive.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
@@ -134,7 +155,7 @@ trait AdditiveCommutativeGroup[@sp(Int, Long, Float, Double) A]
trait AdditiveSemigroupFunctions[S[T] <: AdditiveSemigroup[T]] {
def isAdditiveCommutative[A](implicit ev: S[A]): Boolean =
- ev.isInstanceOf[AdditiveCommutativeSemigroup[_]]
+ ev.isInstanceOf[AdditiveCommutativeSemigroup[?]]
def plus[@sp(Int, Long, Float, Double) A](x: A, y: A)(implicit ev: S[A]): A =
ev.plus(x, y)
diff --git a/algebra-core/src/main/scala/algebra/ring/BoolRing.scala b/algebra-core/src/main/scala/algebra/ring/BoolRing.scala
index 354c336d44..f2cc56c64c 100644
--- a/algebra-core/src/main/scala/algebra/ring/BoolRing.scala
+++ b/algebra-core/src/main/scala/algebra/ring/BoolRing.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/BoolRng.scala b/algebra-core/src/main/scala/algebra/ring/BoolRng.scala
index 78ff3d0c73..72e986daac 100644
--- a/algebra-core/src/main/scala/algebra/ring/BoolRng.scala
+++ b/algebra-core/src/main/scala/algebra/ring/BoolRng.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/CommutativeRig.scala b/algebra-core/src/main/scala/algebra/ring/CommutativeRig.scala
index 751b2d5950..513f4ad471 100644
--- a/algebra-core/src/main/scala/algebra/ring/CommutativeRig.scala
+++ b/algebra-core/src/main/scala/algebra/ring/CommutativeRig.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/CommutativeRing.scala b/algebra-core/src/main/scala/algebra/ring/CommutativeRing.scala
index 59d03576c0..469e7085cc 100644
--- a/algebra-core/src/main/scala/algebra/ring/CommutativeRing.scala
+++ b/algebra-core/src/main/scala/algebra/ring/CommutativeRing.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/CommutativeRng.scala b/algebra-core/src/main/scala/algebra/ring/CommutativeRng.scala
index f7ad06d4f4..e219579d5a 100644
--- a/algebra-core/src/main/scala/algebra/ring/CommutativeRng.scala
+++ b/algebra-core/src/main/scala/algebra/ring/CommutativeRng.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/CommutativeSemifield.scala b/algebra-core/src/main/scala/algebra/ring/CommutativeSemifield.scala
index 796b9b0865..67655be7a7 100644
--- a/algebra-core/src/main/scala/algebra/ring/CommutativeSemifield.scala
+++ b/algebra-core/src/main/scala/algebra/ring/CommutativeSemifield.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/CommutativeSemiring.scala b/algebra-core/src/main/scala/algebra/ring/CommutativeSemiring.scala
index 571e674e12..efdeb65e9b 100644
--- a/algebra-core/src/main/scala/algebra/ring/CommutativeSemiring.scala
+++ b/algebra-core/src/main/scala/algebra/ring/CommutativeSemiring.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/DivisionRing.scala b/algebra-core/src/main/scala/algebra/ring/DivisionRing.scala
index 5fb6761528..aa46eaba5a 100644
--- a/algebra-core/src/main/scala/algebra/ring/DivisionRing.scala
+++ b/algebra-core/src/main/scala/algebra/ring/DivisionRing.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
@@ -10,7 +31,7 @@ trait DivisionRing[@sp(Byte, Short, Int, Long, Float, Double) A] extends Any wit
* This is implemented in terms of basic Ring ops. However, this is
* probably significantly less efficient than can be done with a
* specific type. So, it is recommended that this method be
- * overriden.
+ * overridden.
*
* This is possible because a Double is a rational number.
*/
diff --git a/algebra-core/src/main/scala/algebra/ring/EuclideanRing.scala b/algebra-core/src/main/scala/algebra/ring/EuclideanRing.scala
index 450e34e90f..60fbf80765 100644
--- a/algebra-core/src/main/scala/algebra/ring/EuclideanRing.scala
+++ b/algebra-core/src/main/scala/algebra/ring/EuclideanRing.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/Field.scala b/algebra-core/src/main/scala/algebra/ring/Field.scala
index 86ad93d781..41d3f87be1 100644
--- a/algebra-core/src/main/scala/algebra/ring/Field.scala
+++ b/algebra-core/src/main/scala/algebra/ring/Field.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/GCDRing.scala b/algebra-core/src/main/scala/algebra/ring/GCDRing.scala
index a2031f36a4..db76d6e236 100644
--- a/algebra-core/src/main/scala/algebra/ring/GCDRing.scala
+++ b/algebra-core/src/main/scala/algebra/ring/GCDRing.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/Multiplicative.scala b/algebra-core/src/main/scala/algebra/ring/Multiplicative.scala
index d9d51014eb..5d2a234dc3 100644
--- a/algebra-core/src/main/scala/algebra/ring/Multiplicative.scala
+++ b/algebra-core/src/main/scala/algebra/ring/Multiplicative.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
@@ -5,10 +26,7 @@ import scala.{specialized => sp}
import scala.annotation.{nowarn, tailrec}
trait MultiplicativeSemigroup[@sp(Int, Long, Float, Double) A] extends Any with Serializable {
- def multiplicative: Semigroup[A] =
- new Semigroup[A] {
- def combine(x: A, y: A): A = times(x, y)
- }
+ def multiplicative: Semigroup[A] = times(_, _)
def times(x: A, y: A): A
@@ -37,9 +55,7 @@ trait MultiplicativeSemigroup[@sp(Int, Long, Float, Double) A] extends Any with
}
trait MultiplicativeCommutativeSemigroup[@sp(Int, Long, Float, Double) A] extends Any with MultiplicativeSemigroup[A] {
- override def multiplicative: CommutativeSemigroup[A] = new CommutativeSemigroup[A] {
- def combine(x: A, y: A): A = times(x, y)
- }
+ override def multiplicative: CommutativeSemigroup[A] = times(_, _)
}
trait MultiplicativeMonoid[@sp(Int, Long, Float, Double) A] extends Any with MultiplicativeSemigroup[A] {
diff --git a/algebra-core/src/main/scala/algebra/ring/Rig.scala b/algebra-core/src/main/scala/algebra/ring/Rig.scala
index 532866acaf..04734999ea 100644
--- a/algebra-core/src/main/scala/algebra/ring/Rig.scala
+++ b/algebra-core/src/main/scala/algebra/ring/Rig.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/Ring.scala b/algebra-core/src/main/scala/algebra/ring/Ring.scala
index 6606817046..f295b13153 100644
--- a/algebra-core/src/main/scala/algebra/ring/Ring.scala
+++ b/algebra-core/src/main/scala/algebra/ring/Ring.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/Rng.scala b/algebra-core/src/main/scala/algebra/ring/Rng.scala
index 94585327b5..19c668c2b3 100644
--- a/algebra-core/src/main/scala/algebra/ring/Rng.scala
+++ b/algebra-core/src/main/scala/algebra/ring/Rng.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/Semifield.scala b/algebra-core/src/main/scala/algebra/ring/Semifield.scala
index 31eb3fb41a..b19ef820b6 100644
--- a/algebra-core/src/main/scala/algebra/ring/Semifield.scala
+++ b/algebra-core/src/main/scala/algebra/ring/Semifield.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/Semiring.scala b/algebra-core/src/main/scala/algebra/ring/Semiring.scala
index ef9ca42420..d389b3816f 100644
--- a/algebra-core/src/main/scala/algebra/ring/Semiring.scala
+++ b/algebra-core/src/main/scala/algebra/ring/Semiring.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package ring
diff --git a/algebra-core/src/main/scala/algebra/ring/Signed.scala b/algebra-core/src/main/scala/algebra/ring/Signed.scala
index 1326cb24a3..e7d3e1b061 100644
--- a/algebra-core/src/main/scala/algebra/ring/Signed.scala
+++ b/algebra-core/src/main/scala/algebra/ring/Signed.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.ring
import algebra.{CommutativeMonoid, Eq, Order}
diff --git a/algebra-core/src/main/scala/algebra/ring/TruncatedDivision.scala b/algebra-core/src/main/scala/algebra/ring/TruncatedDivision.scala
index 443bcdb387..5480cef689 100644
--- a/algebra-core/src/main/scala/algebra/ring/TruncatedDivision.scala
+++ b/algebra-core/src/main/scala/algebra/ring/TruncatedDivision.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.ring
import scala.{specialized => sp}
diff --git a/algebra-core/src/test/scala/algebra/Instances.scala b/algebra-core/src/test/scala/algebra/Instances.scala
index b7dd2e1854..f374c9ffdc 100644
--- a/algebra-core/src/test/scala/algebra/Instances.scala
+++ b/algebra-core/src/test/scala/algebra/Instances.scala
@@ -1,13 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
object Instances {
- def t2HasSemigroup[A, B](implicit eva: Semigroup[A], evb: Semigroup[B]) =
- new Semigroup[(A, B)] {
- def combine(x: (A, B), y: (A, B)): (A, B) =
- (eva.combine(x._1, y._1), evb.combine(x._2, y._2))
- }
-
val stringHasMonoid =
new Monoid[String] {
def empty: String = ""
diff --git a/algebra-core/src/test/scala/algebra/ring/RingTest.scala b/algebra-core/src/test/scala/algebra/ring/RingTest.scala
index 865a3e56f8..3be03abc4c 100644
--- a/algebra-core/src/test/scala/algebra/ring/RingTest.scala
+++ b/algebra-core/src/test/scala/algebra/ring/RingTest.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.ring
import algebra.instances.bigInt._
diff --git a/algebra-laws/js/src/main/scala/algebra/laws/platform/Platform.scala b/algebra-laws/js/src/main/scala/algebra/laws/platform/Platform.scala
index adeea18df3..b22423f7bc 100644
--- a/algebra-laws/js/src/main/scala/algebra/laws/platform/Platform.scala
+++ b/algebra-laws/js/src/main/scala/algebra/laws/platform/Platform.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws.platform
private[laws] object Platform {
diff --git a/algebra-laws/jvm/src/main/scala/algebra/laws/platform/Platform.scala b/algebra-laws/jvm/src/main/scala/algebra/laws/platform/Platform.scala
index e4a14708bc..ee3c3bc40c 100644
--- a/algebra-laws/jvm/src/main/scala/algebra/laws/platform/Platform.scala
+++ b/algebra-laws/jvm/src/main/scala/algebra/laws/platform/Platform.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws.platform
private[laws] object Platform {
diff --git a/algebra-laws/native/src/main/scala/algebra/laws/platform/Platform.scala b/algebra-laws/native/src/main/scala/algebra/laws/platform/Platform.scala
index dac1c22e89..4d80a6d80e 100644
--- a/algebra-laws/native/src/main/scala/algebra/laws/platform/Platform.scala
+++ b/algebra-laws/native/src/main/scala/algebra/laws/platform/Platform.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws.platform
private[laws] object Platform {
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/BaseLaws.scala b/algebra-laws/shared/src/main/scala/algebra/laws/BaseLaws.scala
index 11b2c89a3a..c83ce69bae 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/BaseLaws.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/BaseLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws
import cats.kernel._
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/CheckSupport.scala b/algebra-laws/shared/src/main/scala/algebra/laws/CheckSupport.scala
index 6f95634f97..f67ba3cc0a 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/CheckSupport.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/CheckSupport.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws
/**
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/DeMorganLaws.scala b/algebra-laws/shared/src/main/scala/algebra/laws/DeMorganLaws.scala
index cd75fd8092..a0ed8e8935 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/DeMorganLaws.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/DeMorganLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws
import algebra._
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/GroupLaws.scala b/algebra-laws/shared/src/main/scala/algebra/laws/GroupLaws.scala
index 14fac2e575..75860c8bee 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/GroupLaws.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/GroupLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws
import cats.kernel._
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/LatticeLaws.scala b/algebra-laws/shared/src/main/scala/algebra/laws/LatticeLaws.scala
index 76212e1733..631ae07c13 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/LatticeLaws.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/LatticeLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws
import algebra._
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/LatticePartialOrderLaws.scala b/algebra-laws/shared/src/main/scala/algebra/laws/LatticePartialOrderLaws.scala
index db3d17a649..f218e32eb2 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/LatticePartialOrderLaws.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/LatticePartialOrderLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws
import algebra._
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/LogicLaws.scala b/algebra-laws/shared/src/main/scala/algebra/laws/LogicLaws.scala
index 7b42fe3ff7..cbab31e3ad 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/LogicLaws.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/LogicLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws
import algebra._
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/OrderLaws.scala b/algebra-laws/shared/src/main/scala/algebra/laws/OrderLaws.scala
index 5a2aecae10..80c3a6bc97 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/OrderLaws.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/OrderLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws
import cats.kernel._
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/RingLaws.scala b/algebra-laws/shared/src/main/scala/algebra/laws/RingLaws.scala
index 250febaf8d..ba562dc476 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/RingLaws.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/RingLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package laws
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/Rules.scala b/algebra-laws/shared/src/main/scala/algebra/laws/Rules.scala
index 32a62bbc9e..f75d8d6811 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/Rules.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/Rules.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws
import cats.kernel._
@@ -78,7 +99,7 @@ object Rules {
}
def collect0[A: Arbitrary: Eq](name: String, sym: String, id: A)(c: Seq[A] => A): (String, Prop) =
- s"$name(Nil) == $sym" -> forAll { (a: A) =>
+ s"$name(Nil) == $sym" -> forAll { (_: A) =>
c(Nil) ?== id
}
diff --git a/algebra-laws/shared/src/main/scala/algebra/laws/package.scala b/algebra-laws/shared/src/main/scala/algebra/laws/package.scala
index 304e97d17e..9d3d7109e4 100644
--- a/algebra-laws/shared/src/main/scala/algebra/laws/package.scala
+++ b/algebra-laws/shared/src/main/scala/algebra/laws/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
import org.scalacheck._
diff --git a/algebra-laws/shared/src/test/scala/algebra/laws/FPApprox.scala b/algebra-laws/shared/src/test/scala/algebra/laws/FPApprox.scala
index 0cedcd686e..320e78962e 100644
--- a/algebra-laws/shared/src/test/scala/algebra/laws/FPApprox.scala
+++ b/algebra-laws/shared/src/test/scala/algebra/laws/FPApprox.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra.laws
import java.lang.{Double => JDouble, Float => JFloat}
@@ -103,23 +124,14 @@ object FPApprox {
implicit def fpApproxAlgebra[A: Field: Order: Epsilon]: FPApproxAlgebra[A] = new FPApproxAlgebra[A]
// An Eq instance that returns true if 2 values *could* be equal.
- implicit def fpApproxEq[A: Field: Order: Epsilon]: Eq[FPApprox[A]] =
- new Eq[FPApprox[A]] {
- def eqv(x: FPApprox[A], y: FPApprox[A]): Boolean = {
- // We want to check if z +/- error contains 0
- if (x.approx == y.approx) {
- true
- } else {
- val z = x - y
- val err = z.error
- if (Epsilon.isFinite(err)) {
- Order.lteqv(Ring[A].minus(z.approx, err), Ring[A].zero) &&
- Order.gteqv(Ring[A].plus(z.approx, err), Ring[A].zero)
- } else {
- true
- }
- }
- }
+ implicit def fpApproxEq[A: Field: Order: Epsilon]: Eq[FPApprox[A]] = (x, y) =>
+ // We want to check if z +/- error contains 0
+ x.approx == y.approx || {
+ val z = x - y
+ val err = z.error
+ !Epsilon.isFinite(err) ||
+ Order.lteqv(Ring[A].minus(z.approx, err), Ring[A].zero) &&
+ Order.gteqv(Ring[A].plus(z.approx, err), Ring[A].zero)
}
implicit def arbFPApprox[A: Rng: Order: Arbitrary]: Arbitrary[FPApprox[A]] =
diff --git a/algebra-laws/shared/src/test/scala/algebra/laws/LawTests.scala b/algebra-laws/shared/src/test/scala/algebra/laws/LawTests.scala
index 2982b74a0d..54bab5251d 100644
--- a/algebra-laws/shared/src/test/scala/algebra/laws/LawTests.scala
+++ b/algebra-laws/shared/src/test/scala/algebra/laws/LawTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package laws
@@ -156,13 +177,11 @@ class LawTests extends munit.DisciplineSuite {
implicit val NOrderEq: Eq[Order[N]] = Eq.by { (order: Order[N]) =>
Vector.tabulate(nMax)(N).sorted(order.toOrdering)
}
- implicit val NEqEq: Eq[Eq[N]] = new Eq[Eq[N]] {
- def eqv(a: Eq[N], b: Eq[N]) =
- Iterator
- .tabulate(nMax)(N)
- .flatMap { x => Iterator.tabulate(nMax)(N).map((x, _)) }
- .forall { case (x, y) => a.eqv(x, y) == b.eqv(x, y) }
- }
+ implicit val NEqEq: Eq[Eq[N]] = (a, b) =>
+ Iterator
+ .tabulate(nMax)(N)
+ .flatMap { x => Iterator.tabulate(nMax)(N).map((x, _)) }
+ .forall { case (x, y) => a.eqv(x, y) == b.eqv(x, y) }
implicit val monoidOrderN: Monoid[Order[N]] = Order.whenEqualMonoid[N]
checkAll("Order[N]", GroupLaws[Order[N]].monoid)
diff --git a/algebra-laws/shared/src/test/scala/algebra/laws/Rat.scala b/algebra-laws/shared/src/test/scala/algebra/laws/Rat.scala
index 8180c2c00b..1fa2a8c591 100644
--- a/algebra-laws/shared/src/test/scala/algebra/laws/Rat.scala
+++ b/algebra-laws/shared/src/test/scala/algebra/laws/Rat.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package laws
@@ -31,7 +52,7 @@ class Rat(val num: BigInt, val den: BigInt) extends Serializable { lhs =>
def signum: Int = num.signum
def +(rhs: Rat): Rat =
- Rat((lhs.num * rhs.den) + (rhs.num * lhs.den), (lhs.den * rhs.den))
+ Rat((lhs.num * rhs.den) + (rhs.num * lhs.den), lhs.den * rhs.den)
def unary_- : Rat =
Rat(-lhs.num, lhs.den)
diff --git a/algebra-laws/shared/src/test/scala/algebra/laws/SimpleDeMorgan.scala b/algebra-laws/shared/src/test/scala/algebra/laws/SimpleDeMorgan.scala
index 70fa772cca..a11b503a50 100644
--- a/algebra-laws/shared/src/test/scala/algebra/laws/SimpleDeMorgan.scala
+++ b/algebra-laws/shared/src/test/scala/algebra/laws/SimpleDeMorgan.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package laws
@@ -47,7 +68,6 @@ object SimpleDeMorgan {
implicit val arbitrary: Arbitrary[SimpleDeMorgan] = Arbitrary(oneOf(False, Unknown, True))
- implicit val eq: Eq[SimpleDeMorgan] = new Eq[SimpleDeMorgan] {
- def eqv(x: SimpleDeMorgan, y: SimpleDeMorgan): Boolean = x == y
- }
+ implicit val eq: Eq[SimpleDeMorgan] =
+ Eq.fromUniversalEquals
}
diff --git a/algebra-laws/shared/src/test/scala/algebra/laws/SimpleHeyting.scala b/algebra-laws/shared/src/test/scala/algebra/laws/SimpleHeyting.scala
index 5b8d20ff65..c21bf1458c 100644
--- a/algebra-laws/shared/src/test/scala/algebra/laws/SimpleHeyting.scala
+++ b/algebra-laws/shared/src/test/scala/algebra/laws/SimpleHeyting.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package algebra
package laws
@@ -53,7 +74,6 @@ object SimpleHeyting {
implicit val arbitrary: Arbitrary[SimpleHeyting] = Arbitrary(oneOf(Zero, Half, One))
- implicit val eq: Eq[SimpleHeyting] = new Eq[SimpleHeyting] {
- def eqv(x: SimpleHeyting, y: SimpleHeyting): Boolean = x == y
- }
+ implicit val eq: Eq[SimpleHeyting] =
+ Eq.fromUniversalEquals
}
diff --git a/alleycats-core/src/main/scala-2.12/alleycats/compat/IterableEmptyInstance.scala b/alleycats-core/src/main/scala-2.12/alleycats/compat/IterableEmptyInstance.scala
index f46a9595c4..f4bf82e3e5 100644
--- a/alleycats-core/src/main/scala-2.12/alleycats/compat/IterableEmptyInstance.scala
+++ b/alleycats-core/src/main/scala-2.12/alleycats/compat/IterableEmptyInstance.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package compat
diff --git a/alleycats-core/src/main/scala-2.12/alleycats/compat/scalaVersionSpecific.scala b/alleycats-core/src/main/scala-2.12/alleycats/compat/scalaVersionSpecific.scala
index 13db1ea447..bd3ad8091d 100644
--- a/alleycats-core/src/main/scala-2.12/alleycats/compat/scalaVersionSpecific.scala
+++ b/alleycats-core/src/main/scala-2.12/alleycats/compat/scalaVersionSpecific.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats.compat
import scala.annotation.{Annotation, StaticAnnotation}
diff --git a/alleycats-core/src/main/scala-2.13+/alleycats/compat/IterableEmptyInstance.scala b/alleycats-core/src/main/scala-2.13+/alleycats/compat/IterableEmptyInstance.scala
index 45350dde5b..b162066b4b 100644
--- a/alleycats-core/src/main/scala-2.13+/alleycats/compat/IterableEmptyInstance.scala
+++ b/alleycats-core/src/main/scala-2.13+/alleycats/compat/IterableEmptyInstance.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package compat
diff --git a/alleycats-core/src/main/scala-2.13+/alleycats/compat/scalaVersionSpecific.scala b/alleycats-core/src/main/scala-2.13+/alleycats/compat/scalaVersionSpecific.scala
index 18e1715db3..d3608008b1 100644
--- a/alleycats-core/src/main/scala-2.13+/alleycats/compat/scalaVersionSpecific.scala
+++ b/alleycats-core/src/main/scala-2.13+/alleycats/compat/scalaVersionSpecific.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package compat
import scala.annotation.{Annotation, StaticAnnotation}
diff --git a/alleycats-core/src/main/scala/alleycats/ConsK.scala b/alleycats-core/src/main/scala/alleycats/ConsK.scala
index 73beca8a3e..d2ba4471b5 100644
--- a/alleycats-core/src/main/scala/alleycats/ConsK.scala
+++ b/alleycats-core/src/main/scala/alleycats/ConsK.scala
@@ -1,11 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
import cats.SemigroupK
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-@implicitNotFound("Could not find an instance of ConsK for ${F}")
-@typeclass trait ConsK[F[_]] extends Serializable {
+trait ConsK[F[_]] extends Serializable {
def cons[A](hd: A, tl: F[A]): F[A]
}
@@ -15,10 +33,6 @@ object ConsK {
def cons[A](hd: A, tl: F[A]): F[A] = s.combineK(p.pure(hd), tl)
}
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[ConsK]] for `F`.
*/
@@ -54,8 +68,4 @@ object ConsK {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToConsKOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/alleycats-core/src/main/scala/alleycats/Empty.scala b/alleycats-core/src/main/scala/alleycats/Empty.scala
index 3a7d0ebf34..7ae2bd74cc 100644
--- a/alleycats-core/src/main/scala/alleycats/Empty.scala
+++ b/alleycats-core/src/main/scala/alleycats/Empty.scala
@@ -1,13 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
import cats.{Eq, Monoid}
import cats.syntax.eq._
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
-@implicitNotFound("Could not find an instance of Empty for ${A}")
-@typeclass trait Empty[A] extends Serializable {
+trait Empty[A] extends Serializable {
def empty: A
def isEmpty(a: A)(implicit ev: Eq[A]): Boolean =
@@ -23,10 +40,6 @@ object Empty extends EmptyInstances0 {
def fromEmptyK[F[_], T](implicit ekf: EmptyK[F]): Empty[F[T]] = ekf.synthesize[T]
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Empty]] for `A`.
*/
@@ -64,10 +77,6 @@ object Empty extends EmptyInstances0 {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToEmptyOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[alleycats] trait EmptyInstances0 extends compat.IterableEmptyInstance with EmptyInstances1
diff --git a/alleycats-core/src/main/scala/alleycats/EmptyK.scala b/alleycats-core/src/main/scala/alleycats/EmptyK.scala
index 13a900ae7a..314d1c6e78 100644
--- a/alleycats-core/src/main/scala/alleycats/EmptyK.scala
+++ b/alleycats-core/src/main/scala/alleycats/EmptyK.scala
@@ -1,10 +1,27 @@
-package alleycats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package alleycats
-@implicitNotFound("Could not find an instance of EmptyK for ${F}")
-@typeclass trait EmptyK[F[_]] extends Serializable { self =>
+trait EmptyK[F[_]] extends Serializable { self =>
def empty[A]: F[A]
def synthesize[A]: Empty[F[A]] =
@@ -15,10 +32,6 @@ import scala.annotation.implicitNotFound
object EmptyK extends EmptyKInstances0 {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[EmptyK]] for `F`.
*/
@@ -54,10 +67,6 @@ object EmptyK extends EmptyKInstances0 {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToEmptyKOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[alleycats] trait EmptyKInstances0 {
diff --git a/alleycats-core/src/main/scala/alleycats/Extract.scala b/alleycats-core/src/main/scala/alleycats/Extract.scala
index f8e5e0dd25..26f12247c9 100644
--- a/alleycats-core/src/main/scala/alleycats/Extract.scala
+++ b/alleycats-core/src/main/scala/alleycats/Extract.scala
@@ -1,12 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
import cats.{CoflatMap, Comonad}
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
-@implicitNotFound("Could not find an instance of Extract for ${F}")
-@typeclass trait Extract[F[_]] extends Serializable {
+trait Extract[F[_]] extends Serializable {
def extract[A](fa: F[A]): A
}
@@ -25,10 +42,6 @@ object Extract {
def coflatMap[A, B](fa: F[A])(f: F[A] => B): F[B] = cf.coflatMap(fa)(f)
}
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Extract]] for `F`.
*/
@@ -65,8 +78,4 @@ object Extract {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToExtractOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/alleycats-core/src/main/scala/alleycats/One.scala b/alleycats-core/src/main/scala/alleycats/One.scala
index 65dbeed9c2..471f5b1e80 100644
--- a/alleycats-core/src/main/scala/alleycats/One.scala
+++ b/alleycats-core/src/main/scala/alleycats/One.scala
@@ -1,12 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
import cats.Eq
import cats.syntax.eq._
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-@implicitNotFound("Could not find an instance of One for ${A}")
-@typeclass trait One[A] extends Serializable {
+trait One[A] extends Serializable {
def one: A
def isOne(a: A)(implicit ev: Eq[A]): Boolean =
@@ -20,10 +38,6 @@ object One {
def apply[A](a: => A): One[A] =
new One[A] { lazy val one: A = a }
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[One]] for `A`.
*/
@@ -61,8 +75,4 @@ object One {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToOneOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/alleycats-core/src/main/scala/alleycats/Pure.scala b/alleycats-core/src/main/scala/alleycats/Pure.scala
index 6cf116be32..bf57adc62a 100644
--- a/alleycats-core/src/main/scala/alleycats/Pure.scala
+++ b/alleycats-core/src/main/scala/alleycats/Pure.scala
@@ -1,11 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
import cats.{Applicative, FlatMap, Monad}
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-@implicitNotFound("Could not find an instance of Pure for ${F}")
-@typeclass trait Pure[F[_]] extends Serializable {
+trait Pure[F[_]] extends Serializable {
def pure[A](a: A): F[A]
}
@@ -25,10 +43,6 @@ object Pure {
def tailRecM[A, B](a: A)(f: (A) => F[Either[A, B]]): F[B] = fm.tailRecM(a)(f)
}
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Pure]] for `F`.
*/
@@ -64,8 +78,4 @@ object Pure {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToPureOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/alleycats-core/src/main/scala/alleycats/ReferentialEq.scala b/alleycats-core/src/main/scala/alleycats/ReferentialEq.scala
index e922612207..4dc9065c45 100644
--- a/alleycats-core/src/main/scala/alleycats/ReferentialEq.scala
+++ b/alleycats-core/src/main/scala/alleycats/ReferentialEq.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
import cats.Eq
diff --git a/alleycats-core/src/main/scala/alleycats/SystemIdentityHash.scala b/alleycats-core/src/main/scala/alleycats/SystemIdentityHash.scala
index 170e07f8c8..10504f1398 100644
--- a/alleycats-core/src/main/scala/alleycats/SystemIdentityHash.scala
+++ b/alleycats-core/src/main/scala/alleycats/SystemIdentityHash.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
import cats.Hash
diff --git a/alleycats-core/src/main/scala/alleycats/Zero.scala b/alleycats-core/src/main/scala/alleycats/Zero.scala
index 494cf07407..b99febe172 100644
--- a/alleycats-core/src/main/scala/alleycats/Zero.scala
+++ b/alleycats-core/src/main/scala/alleycats/Zero.scala
@@ -1,13 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
import cats.Eq
import cats.syntax.eq._
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
-@implicitNotFound("Could not find an instance of Zero for ${A}")
-@typeclass trait Zero[A] extends Serializable {
+trait Zero[A] extends Serializable {
def zero: A
def isZero(a: A)(implicit ev: Eq[A]): Boolean =
@@ -21,10 +38,6 @@ object Zero {
def apply[A](a: => A): Zero[A] =
new Zero[A] { lazy val zero: A = a }
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Zero]] for `A`.
*/
@@ -62,8 +75,4 @@ object Zero {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToZeroOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/alleycats-core/src/main/scala/alleycats/std/all.scala b/alleycats-core/src/main/scala/alleycats/std/all.scala
index 843b3f40ed..6ae0fa8e12 100644
--- a/alleycats-core/src/main/scala/alleycats/std/all.scala
+++ b/alleycats-core/src/main/scala/alleycats/std/all.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package std
diff --git a/alleycats-core/src/main/scala/alleycats/std/future.scala b/alleycats-core/src/main/scala/alleycats/std/future.scala
index 3ca16ab2d8..bee323ce33 100644
--- a/alleycats-core/src/main/scala/alleycats/std/future.scala
+++ b/alleycats-core/src/main/scala/alleycats/std/future.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package std
diff --git a/alleycats-core/src/main/scala/alleycats/std/iterable.scala b/alleycats-core/src/main/scala/alleycats/std/iterable.scala
index 3c19a5cd3d..32a2eb598c 100644
--- a/alleycats-core/src/main/scala/alleycats/std/iterable.scala
+++ b/alleycats-core/src/main/scala/alleycats/std/iterable.scala
@@ -1,13 +1,38 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package std
-import cats.{Eval, Foldable, Monoid}
+import cats.data.Chain
+import cats.kernel.instances.StaticMethods.wrapMutableIndexedSeq
+import cats.{Applicative, Eval, Foldable, Monoid, Traverse, TraverseFilter}
+
+import scala.collection.immutable.{IndexedSeq => ImIndexedSeq}
object iterable extends IterableInstances
trait IterableInstances {
- implicit val alleycatsStdIterableFoldable: Foldable[Iterable] =
- new Foldable[Iterable] {
+ implicit def alleycatsStdIterableTraverse: Traverse[Iterable] =
+ new Traverse[Iterable] {
override def foldLeft[A, B](fa: Iterable[A], b: B)(f: (B, A) => B): B = fa.foldLeft(b)(f)
override def foldRight[A, B](fa: Iterable[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
@@ -35,5 +60,49 @@ trait IterableInstances {
override def isEmpty[A](fa: Iterable[A]): Boolean = fa.isEmpty
override def nonEmpty[A](fa: Iterable[A]): Boolean = fa.nonEmpty
+
+ // Adapted from List and Vector instances.
+ override def traverse[G[_], A, B](fa: Iterable[A])(f: A => G[B])(implicit G: Applicative[G]): G[Iterable[B]] =
+ if (fa.isEmpty) G.pure(Iterable.empty)
+ else G.map(Chain.traverseViaChain(toImIndexedSeq(fa))(f))(_.toVector)
+
+ override def mapAccumulate[S, A, B](init: S, fa: Iterable[A])(f: (S, A) => (S, B)): (S, Iterable[B]) = {
+ val iter = fa.iterator
+ var s = init
+ val vec = Vector.newBuilder[B]
+ while (iter.hasNext) {
+ val (snext, b) = f(s, iter.next())
+ vec += b
+ s = snext
+ }
+ (s, vec.result())
+ }
+
+ override def zipWithIndex[A](fa: Iterable[A]): Iterable[(A, Int)] =
+ fa.zipWithIndex
+
+ override def mapWithIndex[A, B](fa: Iterable[A])(f: (A, Int) => B): Iterable[B] =
+ fa.zipWithIndex.map { case (a, i) => f(a, i) }
}
+
+ implicit def alleycatsStdIterableTraverseFilter: TraverseFilter[Iterable] = new TraverseFilter[Iterable] {
+ override def traverse: Traverse[Iterable] = alleycatsStdIterableTraverse
+
+ override def traverseFilter[G[_], A, B](
+ fa: Iterable[A]
+ )(f: A => G[Option[B]])(implicit G: Applicative[G]): G[Iterable[B]] =
+ if (fa.isEmpty) G.pure(Iterable.empty)
+ else G.map(Chain.traverseFilterViaChain(toImIndexedSeq(fa))(f))(_.toVector)
+ }
+
+ private def toImIndexedSeq[A](fa: Iterable[A]): ImIndexedSeq[A] = fa match {
+ case iseq: ImIndexedSeq[A] => iseq
+ case _ =>
+ val as = collection.mutable.ArrayBuffer[A]()
+ as ++= fa
+ wrapMutableIndexedSeq(as)
+ }
+
+ @deprecated("use alleycatsStdIterableTraverse", "2.7.1")
+ val alleycatsStdIterableFoldable: Foldable[Iterable] = alleycatsStdIterableTraverse
}
diff --git a/alleycats-core/src/main/scala/alleycats/std/list.scala b/alleycats-core/src/main/scala/alleycats/std/list.scala
index e747d5e4fc..f6d1b0ef72 100644
--- a/alleycats-core/src/main/scala/alleycats/std/list.scala
+++ b/alleycats-core/src/main/scala/alleycats/std/list.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package std
diff --git a/alleycats-core/src/main/scala/alleycats/std/map.scala b/alleycats-core/src/main/scala/alleycats/std/map.scala
index f26538da61..87f790780e 100644
--- a/alleycats-core/src/main/scala/alleycats/std/map.scala
+++ b/alleycats-core/src/main/scala/alleycats/std/map.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package std
@@ -24,11 +45,25 @@ trait MapInstances {
G.map(f(a))((k, _))
}) { chain => chain.foldLeft(Map.empty[K, B]) { case (m, (k, b)) => m.updated(k, b) } }
+ override def mapAccumulate[S, A, B](init: S, fa: Map[K, A])(f: (S, A) => (S, B)): (S, Map[K, B]) = {
+ val iter = fa.iterator
+ var s = init
+ val m = Map.newBuilder[K, B]
+ m.sizeHint(fa.size)
+ while (iter.hasNext) {
+ val (k, a) = iter.next()
+ val (snext, b) = f(s, a)
+ m += k -> b
+ s = snext
+ }
+ (s, m.result())
+ }
+
override def map[A, B](fa: Map[K, A])(f: A => B): Map[K, B] =
fa.map { case (k, a) => (k, f(a)) }
def foldLeft[A, B](fa: Map[K, A], b: B)(f: (B, A) => B): B =
- fa.foldLeft(b) { case (x, (k, a)) => f(x, a) }
+ fa.foldLeft(b) { case (x, (_, a)) => f(x, a) }
def foldRight[A, B](fa: Map[K, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
Foldable.iterateRight(fa.values, lb)(f)
diff --git a/alleycats-core/src/main/scala/alleycats/std/option.scala b/alleycats-core/src/main/scala/alleycats/std/option.scala
index 4794b8e262..eb7a6fd809 100644
--- a/alleycats-core/src/main/scala/alleycats/std/option.scala
+++ b/alleycats-core/src/main/scala/alleycats/std/option.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package std
diff --git a/alleycats-core/src/main/scala/alleycats/std/set.scala b/alleycats-core/src/main/scala/alleycats/std/set.scala
index d8a4f5441a..607ddba1f2 100644
--- a/alleycats-core/src/main/scala/alleycats/std/set.scala
+++ b/alleycats-core/src/main/scala/alleycats/std/set.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package std
@@ -10,6 +31,11 @@ object set extends SetInstances
@suppressUnusedImportWarningForScalaVersionSpecific
trait SetInstances {
+ import SetInstances._
+
+ // We use a def instead of val here as a workaround to the MiMa
+ // 'ReversedMissingMethodProblem' error.
+ implicit def alleycatsStdInstancesForSet
// Monad advertises parametricity, but Set relies on using
// universal hash codes and equality, which hurts our ability to
// rely on free theorems.
@@ -34,8 +60,31 @@ trait SetInstances {
// If we accept Monad for Set, we can also have Alternative, as
// Alternative only requires MonoidK (already accepted by cats-core) and
// the Applicative that comes from Monad.
- implicit val alleyCatsStdSetMonad: Monad[Set] with Alternative[Set] =
- new Monad[Set] with Alternative[Set] {
+ : Monad[Set] & Alternative[Set] & Traverse[Set] & TraverseFilter[Set] =
+ alleycatsStdInstancesForSet_
+
+ @deprecated("Use alleycatsStdInstancesForSet", "2.13.0")
+ val alleyCatsSetTraverse: Traverse[Set] = alleycatsStdInstancesForSet_
+ @deprecated("Use alleycatsStdInstancesForSet", "2.13.0")
+ val alleyCatsStdSetMonad: Monad[Set] & Alternative[Set] = alleycatsStdInstancesForSet_
+ @deprecated("Use alleycatsStdInstancesForSet", "2.13.0")
+ val alleyCatsSetTraverseFilter: TraverseFilter[Set] = alleycatsStdInstancesForSet_
+}
+
+private[alleycats] object SetInstances {
+ private val alleycatsStdInstancesForSet_ : Monad[Set] & Alternative[Set] & Traverse[Set] & TraverseFilter[Set] =
+ new Monad[Set] with Alternative[Set] with Traverse[Set] with TraverseFilter[Set] {
+
+ // Since iteration order is not guaranteed for sets, folds and other
+ // traversals may produce different results for input sets which
+ // appear to be the same.
+ val traverse: Traverse[Set] = this
+
+ def traverseFilter[G[_], A, B](fa: Set[A])(f: A => G[Option[B]])(implicit G: Applicative[G]): G[Set[B]] =
+ traverse
+ .foldRight(fa, Eval.now(G.pure(Set.empty[B])))((x, xse) => G.map2Eval(f(x), xse)((i, o) => i.fold(o)(o + _)))
+ .value
+
def pure[A](a: A): Set[A] = Set(a)
override def map[A, B](fa: Set[A])(f: A => B): Set[B] = fa.map(f)
def flatMap[A, B](fa: Set[A])(f: A => Set[B]): Set[B] = fa.flatMap(f)
@@ -48,7 +97,7 @@ trait SetInstances {
if (fa.isEmpty) Eval.now(Set.empty[Z]) // no need to evaluate fb
else fb.map(fb => map2(fa, fb)(f))
- def tailRecM[A, B](a: A)(f: (A) => Set[Either[A, B]]): Set[B] = {
+ def tailRecM[A, B](a: A)(f: A => Set[Either[A, B]]): Set[B] = {
val bldr = Set.newBuilder[B]
@tailrec def go(set: Set[Either[A, B]]): Unit = {
@@ -77,13 +126,7 @@ trait SetInstances {
override def prependK[A](a: A, fa: Set[A]): Set[A] = fa + a
override def appendK[A](fa: Set[A], a: A): Set[A] = fa + a
- }
- // Since iteration order is not guaranteed for sets, folds and other
- // traversals may produce different results for input sets which
- // appear to be the same.
- implicit val alleyCatsSetTraverse: Traverse[Set] =
- new Traverse[Set] {
def foldLeft[A, B](fa: Set[A], b: B)(f: (B, A) => B): B =
fa.foldLeft(b)(f)
def foldRight[A, B](fa: Set[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
@@ -99,6 +142,18 @@ trait SetInstances {
}.value
}
+ override def mapAccumulate[S, A, B](init: S, fa: Set[A])(f: (S, A) => (S, B)): (S, Set[B]) = {
+ val iter = fa.iterator
+ var s = init
+ val set = Set.newBuilder[B]
+ while (iter.hasNext) {
+ val (snext, b) = f(s, iter.next())
+ set += b
+ s = snext
+ }
+ (s, set.result())
+ }
+
override def get[A](fa: Set[A])(idx: Long): Option[A] = {
@tailrec
def go(idx: Int, it: Iterator[A]): Option[A] =
@@ -139,14 +194,4 @@ trait SetInstances {
override def collectFirstSome[A, B](fa: Set[A])(f: A => Option[B]): Option[B] =
fa.collectFirst(Function.unlift(f))
}
-
- implicit val alleyCatsSetTraverseFilter: TraverseFilter[Set] =
- new TraverseFilter[Set] {
- val traverse: Traverse[Set] = alleyCatsSetTraverse
-
- def traverseFilter[G[_], A, B](fa: Set[A])(f: A => G[Option[B]])(implicit G: Applicative[G]): G[Set[B]] =
- traverse
- .foldRight(fa, Eval.now(G.pure(Set.empty[B])))((x, xse) => G.map2Eval(f(x), xse)((i, o) => i.fold(o)(o + _)))
- .value
- }
}
diff --git a/alleycats-core/src/main/scala/alleycats/std/try.scala b/alleycats-core/src/main/scala/alleycats/std/try.scala
index f97bedfb42..111ad0f252 100644
--- a/alleycats-core/src/main/scala/alleycats/std/try.scala
+++ b/alleycats-core/src/main/scala/alleycats/std/try.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package std
diff --git a/alleycats-core/src/main/scala/alleycats/syntax/all.scala b/alleycats-core/src/main/scala/alleycats/syntax/all.scala
index 6347619726..be4a67772e 100644
--- a/alleycats-core/src/main/scala/alleycats/syntax/all.scala
+++ b/alleycats-core/src/main/scala/alleycats/syntax/all.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats.syntax
-object all extends EmptySyntax with FoldableSyntax
+object all extends EmptySyntax with FoldableSyntax with ExtractSyntax
diff --git a/alleycats-core/src/main/scala/alleycats/syntax/empty.scala b/alleycats-core/src/main/scala/alleycats/syntax/empty.scala
index c1e3cfd41e..c5ae45d7f3 100644
--- a/alleycats-core/src/main/scala/alleycats/syntax/empty.scala
+++ b/alleycats-core/src/main/scala/alleycats/syntax/empty.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package syntax
diff --git a/alleycats-core/src/main/scala/alleycats/syntax/extract.scala b/alleycats-core/src/main/scala/alleycats/syntax/extract.scala
new file mode 100644
index 0000000000..78d5272599
--- /dev/null
+++ b/alleycats-core/src/main/scala/alleycats/syntax/extract.scala
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats
+package syntax
+
+import alleycats.Extract
+
+object extract extends ExtractSyntax
+
+trait ExtractSyntax {
+ implicit final def catsSyntaxExtract[F[_], A](fa: F[A]): ExtractOps[F, A] = new ExtractOps[F, A](fa)
+}
+
+final private[alleycats] class ExtractOps[F[_], A](private val fa: F[A]) extends AnyVal {
+ def extract(implicit F: Extract[F]): A = F.extract(fa)
+}
diff --git a/alleycats-core/src/main/scala/alleycats/syntax/foldable.scala b/alleycats-core/src/main/scala/alleycats/syntax/foldable.scala
index f4e4c9a115..9ee4b03028 100644
--- a/alleycats-core/src/main/scala/alleycats/syntax/foldable.scala
+++ b/alleycats-core/src/main/scala/alleycats/syntax/foldable.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package alleycats
package syntax
diff --git a/alleycats-core/src/test/scala/alleycats/SyntaxSuite.scala b/alleycats-core/src/test/scala/alleycats/SyntaxSuite.scala
new file mode 100644
index 0000000000..71a8867f14
--- /dev/null
+++ b/alleycats-core/src/test/scala/alleycats/SyntaxSuite.scala
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats
+
+import cats.{Eq, Foldable}
+import alleycats.syntax.all.{catsSyntaxExtract, EmptyOps, ExtraFoldableOps}
+
+/**
+ * Test that our syntax implicits are working.
+ *
+ * Each method should correspond to one type class worth of syntax.
+ * Ideally, we should be testing every operator or method that we
+ * expect to add to generic parameters. This file is a safeguard
+ * against accidentally breaking (or removing) syntax which was
+ * otherwise untested.
+ *
+ * The strategy here is to create "mock" values of particular types,
+ * and then ensure that the syntax we want is available. We never plan
+ * to run any of these methods, so we don't need real values. All
+ * values in the methods should be generic -- we rely on parametricity
+ * to guarantee that the syntax will be available for any type with
+ * the proper type class instance(s).
+ *
+ * None of these tests should ever run, or do any runtime checks.
+ */
+object SyntaxSuite {
+
+ // pretend we have a value of type A
+ def mock[A]: A = ???
+
+ def testEmpty[A: Empty]: Unit = {
+ val x = mock[A]
+ implicit val y: Eq[A] = mock[Eq[A]]
+ val a0: Boolean = x.isEmpty
+ val a1: Boolean = x.nonEmpty
+ }
+
+ def testFoldable[F[_]: Foldable, A]: Unit = {
+ val x = mock[F[A]]
+ val y = mock[A => Unit]
+ x.foreach(y)
+ }
+
+ def testExtract[F[_]: Extract, A]: Unit = {
+ val x = mock[F[A]]
+ val y = x.extract
+ }
+}
diff --git a/alleycats-laws/js/src/test/scala/alleycats/tests/TestSettings.scala b/alleycats-laws/js/src/test/scala/alleycats/tests/TestSettings.scala
new file mode 100644
index 0000000000..670d4b0262
--- /dev/null
+++ b/alleycats-laws/js/src/test/scala/alleycats/tests/TestSettings.scala
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.tests
+
+import org.scalacheck.Test
+
+trait TestSettings {
+ lazy val checkConfiguration: Test.Parameters =
+ Test.Parameters.default
+ .withMinSuccessfulTests(5)
+ .withMaxDiscardRatio(50.0f)
+ .withMinSize(0)
+ .withWorkers(1)
+}
diff --git a/alleycats-laws/jvm/src/test/scala/alleycats/tests/TestSettings.scala b/alleycats-laws/jvm/src/test/scala/alleycats/tests/TestSettings.scala
new file mode 100644
index 0000000000..27557a9a8b
--- /dev/null
+++ b/alleycats-laws/jvm/src/test/scala/alleycats/tests/TestSettings.scala
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.tests
+
+import org.scalacheck.Test.Parameters
+
+trait TestSettings {
+
+ lazy val checkConfiguration: Parameters =
+ Parameters.default
+ .withMinSuccessfulTests(50)
+ .withMaxDiscardRatio(5.0f)
+ .withMaxSize(10)
+ .withMinSize(0)
+ .withWorkers(1)
+}
diff --git a/alleycats-laws/native/src/test/scala/alleycats/tests/TestSettings.scala b/alleycats-laws/native/src/test/scala/alleycats/tests/TestSettings.scala
new file mode 100644
index 0000000000..27557a9a8b
--- /dev/null
+++ b/alleycats-laws/native/src/test/scala/alleycats/tests/TestSettings.scala
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.tests
+
+import org.scalacheck.Test.Parameters
+
+trait TestSettings {
+
+ lazy val checkConfiguration: Parameters =
+ Parameters.default
+ .withMinSuccessfulTests(50)
+ .withMaxDiscardRatio(5.0f)
+ .withMaxSize(10)
+ .withMinSize(0)
+ .withWorkers(1)
+}
diff --git a/alleycats-laws/shared/src/main/scala/alleycats/laws/discipline/FlatMapRecTests.scala b/alleycats-laws/shared/src/main/scala/alleycats/laws/discipline/FlatMapRecTests.scala
new file mode 100644
index 0000000000..0dbffc607a
--- /dev/null
+++ b/alleycats-laws/shared/src/main/scala/alleycats/laws/discipline/FlatMapRecTests.scala
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.laws.discipline
+
+import cats._
+import cats.laws.FlatMapLaws
+import cats.laws.discipline._
+import org.scalacheck.Arbitrary
+import org.scalacheck.Prop._
+import org.typelevel.discipline.Laws
+
+trait FlatMapRecTests[F[_]] extends Laws {
+ def laws: FlatMapLaws[F]
+
+ def tailRecM[A: Arbitrary](implicit ArbFA: Arbitrary[F[A]], ArbAFA: Arbitrary[A => F[A]], EqFA: Eq[F[A]]): RuleSet =
+ new DefaultRuleSet(
+ name = "flatMapTailRec",
+ parent = None,
+ "tailRecM consistent flatMap" -> forAll(laws.tailRecMConsistentFlatMap[A] _)
+ )
+}
+
+object FlatMapRecTests {
+ def apply[F[_]: FlatMap]: FlatMapRecTests[F] =
+ new FlatMapRecTests[F] { def laws: FlatMapLaws[F] = FlatMapLaws[F] }
+}
diff --git a/alleycats-laws/shared/src/main/scala/alleycats/laws/discipline/ReferentialEqTests.scala b/alleycats-laws/shared/src/main/scala/alleycats/laws/discipline/ReferentialEqTests.scala
new file mode 100644
index 0000000000..dcd6b00042
--- /dev/null
+++ b/alleycats-laws/shared/src/main/scala/alleycats/laws/discipline/ReferentialEqTests.scala
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.laws.discipline
+
+import cats.kernel.Eq
+import cats.kernel.laws.EqLaws
+import cats.kernel.laws.discipline._
+import org.scalacheck.Arbitrary
+import org.scalacheck.Prop.forAll
+import org.typelevel.discipline.Laws
+
+trait ReferentialEqTests[A] extends Laws {
+ def laws: EqLaws[A]
+
+ def eqv(implicit arbA: Arbitrary[A]): RuleSet = {
+ implicit val eqA: Eq[A] = laws.E
+ new DefaultRuleSet(
+ "referentialEq",
+ None,
+ "reflexivity eq" -> forAll(laws.reflexivityEq _),
+ "symmetry eq" -> forAll(laws.symmetryEq _),
+ "transitivity eq" -> forAll(laws.transitivityEq _)
+ )
+ }
+}
+
+object ReferentialEqTests {
+ def apply[A: Eq]: ReferentialEqTests[A] = new ReferentialEqTests[A] {
+ override def laws: EqLaws[A] = EqLaws[A]
+ }
+}
diff --git a/alleycats-laws/shared/src/main/scala/alleycats/laws/discipline/SystemIdentityHashTests.scala b/alleycats-laws/shared/src/main/scala/alleycats/laws/discipline/SystemIdentityHashTests.scala
new file mode 100644
index 0000000000..61820862a1
--- /dev/null
+++ b/alleycats-laws/shared/src/main/scala/alleycats/laws/discipline/SystemIdentityHashTests.scala
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.laws.discipline
+
+import cats.kernel.{Eq, Hash}
+import cats.kernel.laws.HashLaws
+import cats.kernel.laws.discipline._
+import org.scalacheck.Arbitrary
+import org.scalacheck.Prop.forAll
+
+import scala.util.hashing.Hashing
+
+trait SystemIdentityHashTests[A] extends ReferentialEqTests[A] {
+ def laws: HashLaws[A]
+
+ def hash(implicit arbA: Arbitrary[A], eqA: Eq[A], hashA: Hashing[A]): RuleSet =
+ new DefaultRuleSet(
+ "systemIdentityHash",
+ Some(eqv),
+ "hash compatibility" -> forAll(laws.hashCompatibility _),
+ "same as universal hash" -> forAll(laws.sameAsUniversalHash _),
+ "same as scala hashing" -> forAll((x: A, y: A) => laws.sameAsScalaHashing(x, y, hashA))
+ )
+}
+
+object SystemIdentityHashTests {
+ def apply[A: Hash]: SystemIdentityHashTests[A] = new SystemIdentityHashTests[A] {
+ override def laws: HashLaws[A] = HashLaws[A]
+ }
+}
diff --git a/alleycats-laws/shared/src/test/scala/alleycats/tests/AlleycatsSuite.scala b/alleycats-laws/shared/src/test/scala/alleycats/tests/AlleycatsSuite.scala
new file mode 100644
index 0000000000..b894e434ee
--- /dev/null
+++ b/alleycats-laws/shared/src/test/scala/alleycats/tests/AlleycatsSuite.scala
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.tests
+
+import alleycats.std.MapInstances
+import cats._
+import cats.instances.all._
+import org.scalacheck.{Arbitrary, Gen}
+import org.scalacheck.Test.Parameters
+
+/**
+ * An opinionated stack of traits to improve consistency and reduce
+ * boilerplate in Alleycats tests. Derived from Cats.
+ */
+trait AlleycatsSuite extends munit.DisciplineSuite with TestSettings with TestInstances with MapInstances {
+ implicit override def scalaCheckTestParameters: Parameters =
+ checkConfiguration
+
+ implicit def EqIterable[A: Eq]: Eq[Iterable[A]] = Eq.by(_.toList)
+}
+
+sealed trait TestInstances {
+ implicit val arbObject: Arbitrary[Object] =
+ // with some probability we select from a small set of objects
+ // otherwise make a totally new one
+ // courtesy of @johnynek
+ Arbitrary(
+ Gen.oneOf(
+ Gen.oneOf(List.fill(5)(new Object)),
+ Arbitrary.arbUnit.arbitrary.map(_ => new Object)
+ )
+ )
+}
diff --git a/alleycats-laws/shared/src/test/scala/alleycats/tests/IterableTests.scala b/alleycats-laws/shared/src/test/scala/alleycats/tests/IterableTests.scala
new file mode 100644
index 0000000000..87277842b4
--- /dev/null
+++ b/alleycats-laws/shared/src/test/scala/alleycats/tests/IterableTests.scala
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.tests
+
+import alleycats.std.all._
+import cats.{Eval, Foldable}
+import cats.instances.all._
+import cats.laws.discipline.{TraverseFilterTests, TraverseTests}
+
+class IterableTests extends AlleycatsSuite {
+
+ test("foldLeft sum == sum") {
+ val it = Iterable(1, 2, 3)
+ assertEquals(Foldable[Iterable].foldLeft(it, 0) { case (b, a) =>
+ a + b
+ },
+ it.sum
+ )
+ }
+
+ test("foldRight early termination") {
+ assertEquals(Foldable[Iterable]
+ .foldRight(Iterable(1, 2, 3), Eval.now("KO")) {
+ case (2, _) => Eval.now("OK")
+ case (a, b) => b
+ }
+ .value,
+ Eval.now("OK").value
+ )
+ }
+
+ checkAll("Traverse[Iterable]", TraverseTests[Iterable].traverse[Int, Int, Int, Set[Int], Option, Option])
+
+ checkAll("TraverseFilter[Iterable]", TraverseFilterTests[Iterable].traverseFilter[Int, Int, Int])
+}
diff --git a/alleycats-laws/shared/src/test/scala/alleycats/tests/MapSuite.scala b/alleycats-laws/shared/src/test/scala/alleycats/tests/MapSuite.scala
new file mode 100644
index 0000000000..b8bccda787
--- /dev/null
+++ b/alleycats-laws/shared/src/test/scala/alleycats/tests/MapSuite.scala
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.tests
+
+import cats.Traverse
+import cats.instances.all._
+import cats.laws.discipline.arbitrary._
+import cats.laws.discipline.{SerializableTests, ShortCircuitingTests, TraverseFilterTests}
+
+class MapSuite extends AlleycatsSuite {
+ checkAll("Traverse[Map[Int, *]]", SerializableTests.serializable(Traverse[Map[Int, *]]))
+
+ checkAll("TraverseFilter[Map[Int, *]]", TraverseFilterTests[Map[Int, *]].traverseFilter[Int, Int, Int])
+
+ checkAll("Map[Int, *]", ShortCircuitingTests[Map[Int, *]].traverseFilter[Int])
+
+ test("traverse is stack-safe") {
+ val items = Map((0 until 100000).map { i => (i.toString, i) }: _*)
+ val sumAll = Traverse[Map[String, *]]
+ .traverse(items) { i => () => i }
+ .apply()
+ .values
+ .sum
+
+ assert(sumAll == items.values.sum)
+ }
+}
diff --git a/alleycats-laws/shared/src/test/scala/alleycats/tests/ReferentialEqSuite.scala b/alleycats-laws/shared/src/test/scala/alleycats/tests/ReferentialEqSuite.scala
new file mode 100644
index 0000000000..b2d093c662
--- /dev/null
+++ b/alleycats-laws/shared/src/test/scala/alleycats/tests/ReferentialEqSuite.scala
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.tests
+
+import alleycats.ReferentialEq
+import alleycats.laws.discipline.ReferentialEqTests
+import cats.kernel.Eq
+
+class ReferentialEqSuite extends AlleycatsSuite {
+ implicit val eqObject: Eq[Object] = ReferentialEq[Object]
+
+ checkAll("ReferentialEq[Object]", ReferentialEqTests[Object].eqv)
+}
diff --git a/alleycats-laws/shared/src/test/scala/alleycats/tests/SetSuite.scala b/alleycats-laws/shared/src/test/scala/alleycats/tests/SetSuite.scala
new file mode 100644
index 0000000000..8b926b34c9
--- /dev/null
+++ b/alleycats-laws/shared/src/test/scala/alleycats/tests/SetSuite.scala
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.tests
+
+import alleycats.laws.discipline._
+import alleycats.std.all._
+import cats.{Alternative, Foldable}
+import cats.instances.all._
+import cats.kernel.laws.discipline.SerializableTests
+import cats.laws.discipline.SemigroupalTests.Isomorphisms
+import cats.laws.discipline.arbitrary._
+import cats.laws.discipline.{AlternativeTests, FunctorTests, ShortCircuitingTests, TraverseFilterTests}
+
+class SetSuite extends AlleycatsSuite {
+ implicit val iso: Isomorphisms[Set] = Isomorphisms.invariant[Set](alleycatsStdInstancesForSet)
+
+ checkAll("FlatMapRec[Set]", FlatMapRecTests[Set].tailRecM[Int])
+
+ checkAll("Foldable[Set]", SerializableTests.serializable(Foldable[Set]))
+
+ checkAll("TraverseFilter[Set]", TraverseFilterTests[Set].traverseFilter[Int, Int, Int])
+
+ checkAll("Set[Int]", AlternativeTests[Set].alternative[Int, Int, Int])
+
+ checkAll("Functor[Int]", FunctorTests[Set].functor[Int, Int, Int])
+
+ checkAll("Alternative[Set]", SerializableTests.serializable(Alternative[Set]))
+
+ checkAll("Set[Int]", ShortCircuitingTests[Set].traverseFilter[Int])
+}
diff --git a/alleycats-laws/shared/src/test/scala/alleycats/tests/SystemIdentityHashSuite.scala b/alleycats-laws/shared/src/test/scala/alleycats/tests/SystemIdentityHashSuite.scala
new file mode 100644
index 0000000000..dff2f91b25
--- /dev/null
+++ b/alleycats-laws/shared/src/test/scala/alleycats/tests/SystemIdentityHashSuite.scala
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package alleycats.tests
+
+import alleycats.SystemIdentityHash
+import alleycats.laws.discipline.SystemIdentityHashTests
+import cats.kernel.Hash
+
+class SystemIdentityHashSuite extends AlleycatsSuite {
+ implicit val hashObject: Hash[Object] = SystemIdentityHash[Object]
+
+ checkAll("SystemIdentityHash[Object]", SystemIdentityHashTests[Object].hash)
+}
diff --git a/alleycats-laws/src/main/scala/alleycats/laws/discipline/FlatMapRecTests.scala b/alleycats-laws/src/main/scala/alleycats/laws/discipline/FlatMapRecTests.scala
deleted file mode 100644
index a34a5f5619..0000000000
--- a/alleycats-laws/src/main/scala/alleycats/laws/discipline/FlatMapRecTests.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package alleycats.laws.discipline
-
-import cats._
-import cats.laws.FlatMapLaws
-import cats.laws.discipline._
-import org.scalacheck.Arbitrary
-import org.scalacheck.Prop._
-import org.typelevel.discipline.Laws
-
-trait FlatMapRecTests[F[_]] extends Laws {
- def laws: FlatMapLaws[F]
-
- def tailRecM[A: Arbitrary](implicit ArbFA: Arbitrary[F[A]], ArbAFA: Arbitrary[A => F[A]], EqFA: Eq[F[A]]): RuleSet =
- new DefaultRuleSet(
- name = "flatMapTailRec",
- parent = None,
- "tailRecM consistent flatMap" -> forAll(laws.tailRecMConsistentFlatMap[A] _)
- )
-}
-
-object FlatMapRecTests {
- def apply[F[_]: FlatMap]: FlatMapRecTests[F] =
- new FlatMapRecTests[F] { def laws: FlatMapLaws[F] = FlatMapLaws[F] }
-}
diff --git a/alleycats-laws/src/main/scala/alleycats/laws/discipline/ReferentialEqTests.scala b/alleycats-laws/src/main/scala/alleycats/laws/discipline/ReferentialEqTests.scala
deleted file mode 100644
index 5bc5c169fc..0000000000
--- a/alleycats-laws/src/main/scala/alleycats/laws/discipline/ReferentialEqTests.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package alleycats.laws.discipline
-
-import cats.kernel.Eq
-import cats.kernel.laws.EqLaws
-import cats.kernel.laws.discipline._
-import org.scalacheck.Arbitrary
-import org.scalacheck.Prop.forAll
-import org.typelevel.discipline.Laws
-
-trait ReferentialEqTests[A] extends Laws {
- def laws: EqLaws[A]
-
- def eqv(implicit arbA: Arbitrary[A]): RuleSet = {
- implicit val eqA: Eq[A] = laws.E
- new DefaultRuleSet(
- "referentialEq",
- None,
- "reflexivity eq" -> forAll(laws.reflexivityEq _),
- "symmetry eq" -> forAll(laws.symmetryEq _),
- "transitivity eq" -> forAll(laws.transitivityEq _)
- )
- }
-}
-
-object ReferentialEqTests {
- def apply[A: Eq]: ReferentialEqTests[A] = new ReferentialEqTests[A] {
- override def laws: EqLaws[A] = EqLaws[A]
- }
-}
diff --git a/alleycats-laws/src/main/scala/alleycats/laws/discipline/SystemIdentityHashTests.scala b/alleycats-laws/src/main/scala/alleycats/laws/discipline/SystemIdentityHashTests.scala
deleted file mode 100644
index 1e88a76010..0000000000
--- a/alleycats-laws/src/main/scala/alleycats/laws/discipline/SystemIdentityHashTests.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package alleycats.laws.discipline
-
-import cats.kernel.{Eq, Hash}
-import cats.kernel.laws.HashLaws
-import cats.kernel.laws.discipline._
-import org.scalacheck.Arbitrary
-import org.scalacheck.Prop.forAll
-
-import scala.util.hashing.Hashing
-
-trait SystemIdentityHashTests[A] extends ReferentialEqTests[A] {
- def laws: HashLaws[A]
-
- def hash(implicit arbA: Arbitrary[A], eqA: Eq[A], hashA: Hashing[A]): RuleSet =
- new DefaultRuleSet(
- "systemIdentityHash",
- Some(eqv),
- "hash compatibility" -> forAll(laws.hashCompatibility _),
- "same as universal hash" -> forAll(laws.sameAsUniversalHash _),
- "same as scala hashing" -> forAll((x: A, y: A) => laws.sameAsScalaHashing(x, y, hashA))
- )
-}
-
-object SystemIdentityHashTests {
- def apply[A: Hash]: SystemIdentityHashTests[A] = new SystemIdentityHashTests[A] {
- override def laws: HashLaws[A] = HashLaws[A]
- }
-}
diff --git a/alleycats-tests/js/src/test/scala/alleycats/tests/TestSettings.scala b/alleycats-tests/js/src/test/scala/alleycats/tests/TestSettings.scala
deleted file mode 100644
index 8a78b1f702..0000000000
--- a/alleycats-tests/js/src/test/scala/alleycats/tests/TestSettings.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package alleycats.tests
-
-import org.scalacheck.Test
-
-trait TestSettings {
- lazy val checkConfiguration: Test.Parameters =
- Test.Parameters.default
- .withMinSuccessfulTests(5)
- .withMaxDiscardRatio(50.0f)
- .withMinSize(0)
- .withWorkers(1)
-}
diff --git a/alleycats-tests/jvm/src/test/scala/alleycats/tests/TestSettings.scala b/alleycats-tests/jvm/src/test/scala/alleycats/tests/TestSettings.scala
deleted file mode 100644
index 423ff01760..0000000000
--- a/alleycats-tests/jvm/src/test/scala/alleycats/tests/TestSettings.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package alleycats.tests
-
-import org.scalacheck.Test.Parameters
-
-trait TestSettings {
-
- lazy val checkConfiguration: Parameters =
- Parameters.default
- .withMinSuccessfulTests(50)
- .withMaxDiscardRatio(5.0f)
- .withMaxSize(10)
- .withMinSize(0)
- .withWorkers(1)
-}
diff --git a/alleycats-tests/native/src/test/scala/alleycats/tests/TestSettings.scala b/alleycats-tests/native/src/test/scala/alleycats/tests/TestSettings.scala
deleted file mode 100644
index 423ff01760..0000000000
--- a/alleycats-tests/native/src/test/scala/alleycats/tests/TestSettings.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package alleycats.tests
-
-import org.scalacheck.Test.Parameters
-
-trait TestSettings {
-
- lazy val checkConfiguration: Parameters =
- Parameters.default
- .withMinSuccessfulTests(50)
- .withMaxDiscardRatio(5.0f)
- .withMaxSize(10)
- .withMinSize(0)
- .withWorkers(1)
-}
diff --git a/alleycats-tests/shared/src/test/scala/alleycats/tests/AlleycatsSuite.scala b/alleycats-tests/shared/src/test/scala/alleycats/tests/AlleycatsSuite.scala
deleted file mode 100644
index 72df380181..0000000000
--- a/alleycats-tests/shared/src/test/scala/alleycats/tests/AlleycatsSuite.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package alleycats.tests
-
-import alleycats.std.MapInstances
-import cats._
-import cats.instances.all._
-import org.scalacheck.{Arbitrary, Gen}
-import org.scalacheck.Test.Parameters
-
-/**
- * An opinionated stack of traits to improve consistency and reduce
- * boilerplate in Alleycats tests. Derived from Cats.
- */
-trait AlleycatsSuite extends munit.DisciplineSuite with TestSettings with TestInstances with MapInstances {
- implicit override def scalaCheckTestParameters: Parameters =
- checkConfiguration
-
- implicit def EqIterable[A: Eq]: Eq[Iterable[A]] = Eq.by(_.toList)
-}
-
-sealed trait TestInstances {
- implicit val arbObject: Arbitrary[Object] =
- // with some probability we select from a small set of objects
- // otherwise make a totally new one
- // courtesy of @johnynek
- Arbitrary(
- Gen.oneOf(
- Gen.oneOf(List.fill(5)(new Object)),
- Arbitrary.arbUnit.arbitrary.map(_ => new Object)
- )
- )
-}
diff --git a/alleycats-tests/shared/src/test/scala/alleycats/tests/IterableTests.scala b/alleycats-tests/shared/src/test/scala/alleycats/tests/IterableTests.scala
deleted file mode 100644
index 28f87d500a..0000000000
--- a/alleycats-tests/shared/src/test/scala/alleycats/tests/IterableTests.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package alleycats.tests
-
-import alleycats.std.all._
-import cats.{Eval, Foldable}
-import cats.instances.all._
-import cats.laws.discipline.FoldableTests
-
-class IterableTests extends AlleycatsSuite {
-
- test("foldLeft sum == sum") {
- val it = Iterable(1, 2, 3)
- assertEquals(Foldable[Iterable].foldLeft(it, 0) { case (b, a) =>
- a + b
- },
- it.sum
- )
- }
-
- test("foldRight early termination") {
- assertEquals(Foldable[Iterable]
- .foldRight(Iterable(1, 2, 3), Eval.now("KO")) {
- case (2, _) => Eval.now("OK")
- case (a, b) => b
- }
- .value,
- Eval.now("OK").value
- )
- }
-
- checkAll("Foldable[Iterable]", FoldableTests[Iterable].foldable[Int, Int])
-}
diff --git a/alleycats-tests/shared/src/test/scala/alleycats/tests/MapSuite.scala b/alleycats-tests/shared/src/test/scala/alleycats/tests/MapSuite.scala
deleted file mode 100644
index 6ae59faa72..0000000000
--- a/alleycats-tests/shared/src/test/scala/alleycats/tests/MapSuite.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package alleycats.tests
-
-import cats.Traverse
-import cats.instances.all._
-import cats.laws.discipline.arbitrary._
-import cats.laws.discipline.{SerializableTests, ShortCircuitingTests, TraverseFilterTests}
-
-class MapSuite extends AlleycatsSuite {
- checkAll("Traverse[Map[Int, *]]", SerializableTests.serializable(Traverse[Map[Int, *]]))
-
- checkAll("TraverseFilter[Map[Int, *]]", TraverseFilterTests[Map[Int, *]].traverseFilter[Int, Int, Int])
-
- checkAll("Map[Int, *]", ShortCircuitingTests[Map[Int, *]].traverseFilter[Int])
-
- test("traverse is stack-safe") {
- val items = Map((0 until 100000).map { i => (i.toString, i) }: _*)
- val sumAll = Traverse[Map[String, *]]
- .traverse(items) { i => () => i }
- .apply()
- .values
- .sum
-
- assert(sumAll == items.values.sum)
- }
-}
diff --git a/alleycats-tests/shared/src/test/scala/alleycats/tests/ReferentialEqSuite.scala b/alleycats-tests/shared/src/test/scala/alleycats/tests/ReferentialEqSuite.scala
deleted file mode 100644
index c4490301a9..0000000000
--- a/alleycats-tests/shared/src/test/scala/alleycats/tests/ReferentialEqSuite.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package alleycats.tests
-
-import alleycats.ReferentialEq
-import alleycats.laws.discipline.ReferentialEqTests
-import cats.kernel.Eq
-
-class ReferentialEqSuite extends AlleycatsSuite {
- implicit val eqObject: Eq[Object] = ReferentialEq[Object]
-
- checkAll("ReferentialEq[Object]", ReferentialEqTests[Object].eqv)
-}
diff --git a/alleycats-tests/shared/src/test/scala/alleycats/tests/SetSuite.scala b/alleycats-tests/shared/src/test/scala/alleycats/tests/SetSuite.scala
deleted file mode 100644
index 07a7c9e49c..0000000000
--- a/alleycats-tests/shared/src/test/scala/alleycats/tests/SetSuite.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package alleycats.tests
-
-import alleycats.laws.discipline._
-import alleycats.std.all._
-import cats.{Alternative, Foldable}
-import cats.instances.all._
-import cats.kernel.laws.discipline.SerializableTests
-import cats.laws.discipline.SemigroupalTests.Isomorphisms
-import cats.laws.discipline.arbitrary._
-import cats.laws.discipline.{AlternativeTests, ShortCircuitingTests, TraverseFilterTests}
-
-class SetSuite extends AlleycatsSuite {
- implicit val iso: Isomorphisms[Set] = Isomorphisms.invariant[Set](alleyCatsStdSetMonad)
-
- checkAll("FlatMapRec[Set]", FlatMapRecTests[Set].tailRecM[Int])
-
- checkAll("Foldable[Set]", SerializableTests.serializable(Foldable[Set]))
-
- checkAll("TraverseFilter[Set]", TraverseFilterTests[Set].traverseFilter[Int, Int, Int])
-
- checkAll("Set[Int]", AlternativeTests[Set].alternative[Int, Int, Int])
- checkAll("Alternative[Set]", SerializableTests.serializable(Alternative[Set]))
-
- checkAll("Set[Int]", ShortCircuitingTests[Set].traverseFilter[Int])
-}
diff --git a/alleycats-tests/shared/src/test/scala/alleycats/tests/SystemIdentityHashSuite.scala b/alleycats-tests/shared/src/test/scala/alleycats/tests/SystemIdentityHashSuite.scala
deleted file mode 100644
index 580b7bef38..0000000000
--- a/alleycats-tests/shared/src/test/scala/alleycats/tests/SystemIdentityHashSuite.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package alleycats.tests
-
-import alleycats.SystemIdentityHash
-import alleycats.laws.discipline.SystemIdentityHashTests
-import cats.kernel.Hash
-
-class SystemIdentityHashSuite extends AlleycatsSuite {
- implicit val hashObject: Hash[Object] = SystemIdentityHash[Object]
-
- checkAll("SystemIdentityHash[Object]", SystemIdentityHashTests[Object].hash)
-}
diff --git a/bench/src/main/scala-2.12/cats/bench/CollectionMonoidBench.scala b/bench/src/main/scala-2.12/cats/bench/CollectionMonoidBench.scala
deleted file mode 100644
index 81d4ec1970..0000000000
--- a/bench/src/main/scala-2.12/cats/bench/CollectionMonoidBench.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package cats.bench
-
-import cats.Monoid
-import cats.data.Chain
-import cats.implicits._
-import chain.{Chain => OldChain}
-import org.openjdk.jmh.annotations.{Benchmark, Scope, State}
-
-@State(Scope.Thread)
-class CollectionMonoidBench {
-
- private val largeList = (0 to 1000000).toList
-
- implicit def monoidOldChain[A]: Monoid[OldChain[A]] = new Monoid[OldChain[A]] {
- def empty: OldChain[A] = OldChain.empty[A]
-
- def combine(x: OldChain[A], y: OldChain[A]): OldChain[A] = x ++ y
- }
-
- @Benchmark def accumulateChain: Chain[Int] = largeList.foldMap(Chain.one)
- @Benchmark def accumulateVector: Vector[Int] = largeList.foldMap(Vector(_))
- @Benchmark def accumulateList: List[Int] = largeList.foldMap(List(_))
- @Benchmark def accumulateOldChain: OldChain[Int] = largeList.foldMap(OldChain.single)
-}
diff --git a/bench/src/main/scala-2.12/cats/bench/ChainBench.scala b/bench/src/main/scala/cats/bench/ChainBench.scala
similarity index 59%
rename from bench/src/main/scala-2.12/cats/bench/ChainBench.scala
rename to bench/src/main/scala/cats/bench/ChainBench.scala
index 8cab9e7a3f..82ced4f098 100644
--- a/bench/src/main/scala-2.12/cats/bench/ChainBench.scala
+++ b/bench/src/main/scala/cats/bench/ChainBench.scala
@@ -1,8 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.bench
import cats.data.Chain
-import fs2.Catenable
-import chain.{Chain => OldChain}
import org.openjdk.jmh.annotations.{Benchmark, Scope, State}
@State(Scope.Thread)
@@ -10,61 +29,47 @@ class ChainBench {
private val intOption = Option(1)
private val smallChain = Chain(1, 2, 3, 4, 5)
- private val smallCatenable = Catenable(1, 2, 3, 4, 5)
private val smallVector = Vector(1, 2, 3, 4, 5)
private val smallList = List(1, 2, 3, 4, 5)
- private val smallOldChain = OldChain(smallList)
private val largeChain = (0 to 1000)
.foldLeft(Chain.empty[Int])((acc, _) => acc ++ Chain.fromSeq(0 to 1000))
- private val largeCatenable = Catenable.fromSeq(0 to 1000000)
private val largeVector = (0 to 1000000).toVector
private val largeList = (0 to 1000000).toList
- private val largeOldChain = (0 to 1000).foldLeft(OldChain.empty[Int])((acc, _) => acc ++ OldChain(0 to 1000))
@Benchmark def mapSmallChain: Chain[Int] = smallChain.map(_ + 1)
- @Benchmark def mapSmallCatenable: Catenable[Int] = smallCatenable.map(_ + 1)
@Benchmark def mapSmallVector: Vector[Int] = smallVector.map(_ + 1)
@Benchmark def mapSmallList: List[Int] = smallList.map(_ + 1)
- @Benchmark def mapSmallOldChain: OldChain[Int] = smallOldChain.map(_ + 1)
@Benchmark def mapLargeChain: Chain[Int] = largeChain.map(_ + 1)
- @Benchmark def mapLargeCatenable: Catenable[Int] = largeCatenable.map(_ + 1)
@Benchmark def mapLargeVector: Vector[Int] = largeVector.map(_ + 1)
@Benchmark def mapLargeList: List[Int] = largeList.map(_ + 1)
- @Benchmark def mapLargeOldChain: OldChain[Int] = largeOldChain.map(_ + 1)
@Benchmark def foldLeftSmallChain: Int = smallChain.foldLeft(0)(_ + _)
- @Benchmark def foldLeftSmallCatenable: Int = smallCatenable.foldLeft(0)(_ + _)
@Benchmark def foldLeftSmallVector: Int = smallVector.foldLeft(0)(_ + _)
@Benchmark def foldLeftSmallList: Int = smallList.foldLeft(0)(_ + _)
- @Benchmark def foldLeftSmallOldChain: Int = smallOldChain.foldLeft(0)(_ + _)
@Benchmark def foldLeftLargeChain: Int = largeChain.foldLeft(0)(_ + _)
- @Benchmark def foldLeftLargeCatenable: Int = largeCatenable.foldLeft(0)(_ + _)
@Benchmark def foldLeftLargeVector: Int = largeVector.foldLeft(0)(_ + _)
@Benchmark def foldLeftLargeList: Int = largeList.foldLeft(0)(_ + _)
- @Benchmark def foldLeftLargeOldChain: Int = largeOldChain.foldLeft(0)(_ + _)
@Benchmark def consSmallChain: Chain[Int] = 0 +: smallChain
- @Benchmark def consSmallCatenable: Catenable[Int] = 0 +: smallCatenable
@Benchmark def consSmallVector: Vector[Int] = 0 +: smallVector
@Benchmark def consSmallList: List[Int] = 0 +: smallList
- @Benchmark def consSmallOldChain: OldChain[Int] = 0 +: smallOldChain
@Benchmark def consLargeChain: Chain[Int] = 0 +: largeChain
- @Benchmark def consLargeCatenable: Catenable[Int] = 0 +: largeCatenable
@Benchmark def consLargeVector: Vector[Int] = 0 +: largeVector
@Benchmark def consLargeList: List[Int] = 0 +: largeList
- @Benchmark def consLargeOldChain: OldChain[Int] = 0 +: largeOldChain
@Benchmark def createTinyChain: Chain[Int] = Chain(1)
- @Benchmark def createTinyCatenable: Catenable[Int] = Catenable(1)
@Benchmark def createTinyVector: Vector[Int] = Vector(1)
@Benchmark def createTinyList: List[Int] = List(1)
- @Benchmark def createTinyOldChain: OldChain[Int] = OldChain.single(1)
@Benchmark def createSmallChain: Chain[Int] = Chain(1, 2, 3, 4, 5)
- @Benchmark def createSmallCatenable: Catenable[Int] = Catenable(1, 2, 3, 4, 5)
@Benchmark def createSmallVector: Vector[Int] = Vector(1, 2, 3, 4, 5)
@Benchmark def createSmallList: List[Int] = List(1, 2, 3, 4, 5)
- @Benchmark def createSmallOldChain: OldChain[Int] = OldChain(Seq(1, 2, 3, 4, 5))
@Benchmark def createChainSeqOption: Chain[Int] = Chain.fromSeq(intOption.toSeq)
@Benchmark def createChainOption: Chain[Int] = Chain.fromOption(intOption)
+
+ @Benchmark def reverseLargeList: List[Int] = largeList.reverse
+ @Benchmark def reverseLargeChain: Chain[Int] = largeChain.reverse
+
+ @Benchmark def lengthLargeList: Int = largeList.length
+ @Benchmark def lengthLargeChain: Long = largeChain.length
}
diff --git a/bench/src/main/scala/cats/bench/CollectionMonoidBench.scala b/bench/src/main/scala/cats/bench/CollectionMonoidBench.scala
new file mode 100644
index 0000000000..0052e29752
--- /dev/null
+++ b/bench/src/main/scala/cats/bench/CollectionMonoidBench.scala
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.bench
+
+import cats.data.Chain
+import cats.syntax.all._
+import org.openjdk.jmh.annotations.{Benchmark, Scope, State}
+
+@State(Scope.Thread)
+class CollectionMonoidBench {
+
+ private val largeList = (0 to 1000000).toList
+
+ @Benchmark def accumulateChain: Chain[Int] = largeList.foldMap(Chain.one)
+ @Benchmark def accumulateVector: Vector[Int] = largeList.foldMap(Vector(_))
+ @Benchmark def accumulateList: List[Int] = largeList.foldMap(List(_))
+}
diff --git a/bench/src/main/scala/cats/bench/EitherKMapBench.scala b/bench/src/main/scala/cats/bench/EitherKMapBench.scala
index ad6415e1e6..cad50d56bb 100644
--- a/bench/src/main/scala/cats/bench/EitherKMapBench.scala
+++ b/bench/src/main/scala/cats/bench/EitherKMapBench.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.bench
import cats.Functor
import cats.data.EitherK
-import cats.implicits._
+import cats.syntax.all._
import org.openjdk.jmh.annotations.{Benchmark, Scope, State}
@State(Scope.Benchmark)
diff --git a/bench/src/main/scala/cats/bench/FoldBench.scala b/bench/src/main/scala/cats/bench/FoldBench.scala
index 8a007cff0c..be7e813ebc 100644
--- a/bench/src/main/scala/cats/bench/FoldBench.scala
+++ b/bench/src/main/scala/cats/bench/FoldBench.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.bench
import cats.data.Const
diff --git a/bench/src/main/scala/cats/bench/FoldMapABench.scala b/bench/src/main/scala/cats/bench/FoldMapABench.scala
index bd67289fa3..01895fa352 100644
--- a/bench/src/main/scala/cats/bench/FoldMapABench.scala
+++ b/bench/src/main/scala/cats/bench/FoldMapABench.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.bench
import cats.Applicative
diff --git a/bench/src/main/scala-2.12/cats/bench/MapMonoidBench.scala b/bench/src/main/scala/cats/bench/MapMonoidBench.scala
similarity index 54%
rename from bench/src/main/scala-2.12/cats/bench/MapMonoidBench.scala
rename to bench/src/main/scala/cats/bench/MapMonoidBench.scala
index 382f892ae3..ac003fb212 100644
--- a/bench/src/main/scala-2.12/cats/bench/MapMonoidBench.scala
+++ b/bench/src/main/scala/cats/bench/MapMonoidBench.scala
@@ -1,13 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.bench
import cats.instances.list._
import cats.instances.int._
import cats.instances.map._
-import scalaz.std.anyVal._
-import scalaz.std.list._
-import scalaz.std.map._
-
import org.openjdk.jmh.annotations.{Benchmark, Scope, State}
@State(Scope.Benchmark)
@@ -29,11 +46,6 @@ class MapMonoidBench {
cats.Monoid[Map[String, Int]].combine(acc, m)
}
- @Benchmark def combineScalaz: Map[String, Int] =
- maps.foldLeft(Map.empty[String, Int]) { case (acc, m) =>
- scalaz.Monoid[Map[String, Int]].append(acc, m)
- }
-
@Benchmark def combineDirect: Map[String, Int] =
maps.foldLeft(Map.empty[String, Int]) { case (acc, m) =>
m.foldLeft(acc) { case (m, (k, v)) =>
@@ -53,7 +65,4 @@ class MapMonoidBench {
@Benchmark def foldMapCats: Map[String, Int] =
cats.Foldable[List].foldMap(maps)(identity)
-
- @Benchmark def foldMapScalaz: Map[String, Int] =
- scalaz.Foldable[List].foldMap(maps)(identity)
}
diff --git a/bench/src/main/scala/cats/bench/ParTraverseBench.scala b/bench/src/main/scala/cats/bench/ParTraverseBench.scala
index e67479d41c..e61aa038a0 100644
--- a/bench/src/main/scala/cats/bench/ParTraverseBench.scala
+++ b/bench/src/main/scala/cats/bench/ParTraverseBench.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.bench
import cats.{Bitraverse, Parallel, Traverse}
diff --git a/bench/src/main/scala/cats/bench/StateTBench.scala b/bench/src/main/scala/cats/bench/StateTBench.scala
index 75964d8ad4..5a9937dc01 100644
--- a/bench/src/main/scala/cats/bench/StateTBench.scala
+++ b/bench/src/main/scala/cats/bench/StateTBench.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.bench
import cats.Eval
diff --git a/bench/src/main/scala/cats/bench/TrampolineBench.scala b/bench/src/main/scala/cats/bench/TrampolineBench.scala
index a80fdd2e93..7b49511349 100644
--- a/bench/src/main/scala/cats/bench/TrampolineBench.scala
+++ b/bench/src/main/scala/cats/bench/TrampolineBench.scala
@@ -1,9 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.bench
import org.openjdk.jmh.annotations.{Benchmark, Scope, State}
import cats._
-import cats.implicits._
+import cats.syntax.all._
import cats.free.Trampoline
import scala.util.control.TailCalls
diff --git a/bench/src/main/scala/cats/bench/TraverseBench.scala b/bench/src/main/scala/cats/bench/TraverseBench.scala
index fd61b603a7..5c967db7b6 100644
--- a/bench/src/main/scala/cats/bench/TraverseBench.scala
+++ b/bench/src/main/scala/cats/bench/TraverseBench.scala
@@ -1,154 +1,292 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.bench
-import cats.{Always, Applicative, Eval, Traverse}
-import cats.instances.either._
-import cats.instances.list._
-import cats.instances.vector._
-import org.openjdk.jmh.annotations.{Benchmark, Scope, State}
+import cats.{Eval, Traverse, TraverseFilter}
+import org.openjdk.jmh.annotations.{Benchmark, Param, Scope, Setup, State}
+import org.openjdk.jmh.infra.Blackhole
+import cats.data.Chain
@State(Scope.Benchmark)
-class TraverseListBench {
- val instance: Traverse[List] = Traverse[List]
- val f: Int => Either[Int, Int] = Right(_)
+class TraverseBench {
+ val listT: Traverse[List] = Traverse[List]
+ val listTFilter: TraverseFilter[List] = TraverseFilter[List]
+ val chainTFilter: TraverseFilter[Chain] = TraverseFilter[Chain]
+
+ val vectorT: Traverse[Vector] = Traverse[Vector]
+ val vectorTFilter: TraverseFilter[Vector] = TraverseFilter[Vector]
+
+ val chainT: Traverse[Chain] = Traverse[Chain]
+
+ // the unit of CPU work per iteration
+ private[this] val Work: Long = 10
+
+ private[this] case object Failure extends RuntimeException
- val xs1: List[Int] = (1 to 10).toList
- val xs2: List[Int] = (1 to 100).toList
- val xs3: List[Int] = (1 to 1000).toList
- val xs4: List[Int] = (1 to 10000).toList
+ @Param(Array("10000"))
+ var length: Int = _
- def traverseCats[G[_], A, B](fa: List[A])(f: A => G[B])(implicit G: Applicative[G]): G[List[B]] =
- instance
- .foldRight[A, G[List[B]]](fa, Always(G.pure(List.empty))) { (a, lglb) =>
- G.map2Eval(f(a), lglb)(_ :: _)
+ var list: List[Int] = _
+ var vector: Vector[Int] = _
+ var chain: Chain[Int] = _
+
+ @Setup
+ def setup(): Unit = {
+ list = 0.until(length).toList
+ vector = 0.until(length).toVector
+ chain = Chain.fromSeq(0.until(length))
+ }
+
+ @Benchmark
+ def traverseList(bh: Blackhole) = {
+ val result = listT.traverse(list) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+ i * 2
}
- .value
+ }
- def traverseFoldRight[G[_], A, B](fa: List[A])(f: A => G[B])(implicit G: Applicative[G]): G[List[B]] =
- fa.foldRight[Eval[G[List[B]]]](Always(G.pure(Nil))) { case (h, t) =>
- G.map2Eval(f(h), Eval.defer(t))(_ :: _)
- }.value
+ bh.consume(result.value)
+ }
+
+ @Benchmark
+ def traverseListError(bh: Blackhole) = {
+ val result = listT.traverse(list) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+
+ if (i == length * 0.3) {
+ throw Failure
+ }
+
+ i * 2
+ }
+ }
+
+ try {
+ bh.consume(result.value)
+ } catch {
+ case Failure => ()
+ }
+ }
- def traverseRec[G[_], A, B](fa: List[A])(f: A => G[B])(implicit G: Applicative[G]): G[List[B]] = {
- def loop(fa: List[A]): Eval[G[List[B]]] = fa match {
- case h :: t => G.map2Eval(f(h), Eval.defer(loop(t)))(_ :: _)
- case Nil => Eval.now(G.pure(Nil))
+ // TODO: consider renaming to `traverseVoidList`
+ @Benchmark
+ def traverse_List(bh: Blackhole): Unit = {
+ val result = listT.traverseVoid(list) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+ i * 2
+ }
}
- loop(fa).value
+
+ bh.consume(result.value)
}
- @Benchmark def traverseCats1: Either[Int, List[Int]] = traverseCats(xs1)(f)
- @Benchmark def traverseCats2: Either[Int, List[Int]] = traverseCats(xs2)(f)
- @Benchmark def traverseCats3: Either[Int, List[Int]] = traverseCats(xs3)(f)
- @Benchmark def traverseCats4: Either[Int, List[Int]] = traverseCats(xs4)(f)
+ @Benchmark
+ def traverseFilterList(bh: Blackhole) = {
+ val result = listTFilter.traverseFilter(list) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+ if (i % 2 == 0) Some(i * 2) else None
+ }
+ }
- @Benchmark def traverseFoldRight1: Either[Int, List[Int]] = traverseFoldRight(xs1)(f)
- @Benchmark def traverseFoldRight2: Either[Int, List[Int]] = traverseFoldRight(xs2)(f)
- @Benchmark def traverseFoldRight3: Either[Int, List[Int]] = traverseFoldRight(xs3)(f)
- @Benchmark def traverseFoldRight4: Either[Int, List[Int]] = traverseFoldRight(xs4)(f)
+ bh.consume(result.value)
+ }
- @Benchmark def traverseRec1: Either[Int, List[Int]] = traverseRec(xs1)(f)
- @Benchmark def traverseRec2: Either[Int, List[Int]] = traverseRec(xs2)(f)
- @Benchmark def traverseRec3: Either[Int, List[Int]] = traverseRec(xs3)(f)
- @Benchmark def traverseRec4: Either[Int, List[Int]] = traverseRec(xs4)(f)
-}
+ @Benchmark
+ def mapList(bh: Blackhole) = {
+ val results = list.map { i =>
+ val inner = Eval.later {
+ Blackhole.consumeCPU(Work)
+ i * 2
+ }
-@State(Scope.Benchmark)
-class TraverseVectorBench {
- val instance: Traverse[Vector] = Traverse[Vector]
- val f: Int => Either[Int, Int] = Right(_)
+ // we just want to force the allocation to level the playing field
+ inner.value
+ }
- val xs1: Vector[Int] = (1 to 10).toVector
- val xs2: Vector[Int] = (1 to 100).toVector
- val xs3: Vector[Int] = (1 to 1000).toVector
- val xs4: Vector[Int] = (1 to 10000).toVector
+ bh.consume(results)
+ }
- def traverseCats[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Vector[B]] =
- instance
- .foldRight[A, G[Vector[B]]](fa, Always(G.pure(Vector.empty))) { (a, lgvb) =>
- G.map2Eval(f(a), lgvb)(_ +: _)
+ @Benchmark
+ def filterList(bh: Blackhole) = {
+ val results = list.flatMap { i =>
+ val inner = Eval.later {
+ Blackhole.consumeCPU(Work)
+ if (i % 2 == 0) Some(i * 2) else None
}
- .value
- def traverseFoldRight[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Vector[B]] =
- fa.foldRight[Eval[G[Vector[B]]]](Always(G.pure(Vector.empty))) { case (h, t) =>
- G.map2Eval(f(h), Eval.defer(t))(_ +: _)
- }.value
+ // we just want to force the allocation to level the playing field
+ inner.value
+ }
- def traverseRec[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Vector[B]] = {
- def loop(i: Int): Eval[G[Vector[B]]] =
- if (i < fa.length) G.map2Eval(f(fa(i)), Eval.defer(loop(i + 1)))(_ +: _) else Eval.now(G.pure(Vector.empty))
- loop(0).value
+ bh.consume(results)
}
- def traverseIter[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Vector[B]] = {
- var i = fa.length - 1
- var current: Eval[G[Vector[B]]] = Eval.now(G.pure(Vector.empty))
+ @Benchmark
+ def traverseVector(bh: Blackhole) = {
+ val result = vectorT.traverse(vector) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+ i * 2
+ }
+ }
+
+ bh.consume(result.value)
+ }
- while (i >= 0) {
- current = G.map2Eval(f(fa(i)), current)(_ +: _)
- i -= 1
+ // TODO: consider renaming to `traverseVoidVector`
+ @Benchmark
+ def traverse_Vector(bh: Blackhole): Unit = {
+ val result = vectorT.traverseVoid(vector) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+ i * 2
+ }
}
- current.value
+ bh.consume(result.value)
}
- def traverseFoldRightViaList[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Vector[B]] =
- G.map(
- fa.foldRight[Eval[G[List[B]]]](Always(G.pure(Nil))) { case (h, t) =>
- G.map2Eval(f(h), Eval.defer(t))(_ :: _)
- }.value
- )(_.toVector)
+ @Benchmark
+ def traverseVectorError(bh: Blackhole) = {
+ val result = vectorT.traverse(vector) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
- def traverseRecViaList[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Vector[B]] = {
- def loop(i: Int): Eval[G[List[B]]] =
- if (i < fa.length) G.map2Eval(f(fa(i)), Eval.defer(loop(i + 1)))(_ :: _) else Eval.now(G.pure(Nil))
- G.map(loop(0).value)(_.toVector)
+ if (i == length * 0.3) {
+ throw Failure
+ }
+
+ i * 2
+ }
+ }
+
+ try {
+ bh.consume(result.value)
+ } catch {
+ case Failure => ()
+ }
}
- def traverseIterViaList[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Vector[B]] = {
- var i = fa.length - 1
- var current: Eval[G[List[B]]] = Eval.now(G.pure(Nil))
+ @Benchmark
+ def traverseFilterVector(bh: Blackhole) = {
+ val result = vectorTFilter.traverseFilter(vector) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+ if (i % 2 == 0) Some(i * 2) else None
+ }
+ }
+
+ bh.consume(result.value)
+ }
- while (i >= 0) {
- current = G.map2Eval(f(fa(i)), current)(_ :: _)
- i -= 1
+ @Benchmark
+ def mapVector(bh: Blackhole) = {
+ val results = vector.map { i =>
+ val inner = Eval.later {
+ Blackhole.consumeCPU(Work)
+ i * 2
+ }
+
+ // we just want to force the allocation to level the playing field
+ inner.value
}
- G.map(current.value)(_.toVector)
+ bh.consume(results)
}
- @Benchmark def traverseCats1: Either[Int, Vector[Int]] = traverseCats(xs1)(f)
- @Benchmark def traverseCats2: Either[Int, Vector[Int]] = traverseCats(xs2)(f)
- @Benchmark def traverseCats3: Either[Int, Vector[Int]] = traverseCats(xs3)(f)
- @Benchmark def traverseCats4: Either[Int, Vector[Int]] = traverseCats(xs4)(f)
+ @Benchmark
+ def filterVector(bh: Blackhole) = {
+ val results = vector.flatMap { i =>
+ val inner = Eval.later {
+ Blackhole.consumeCPU(Work)
+ if (i % 2 == 0) Some(i * 2) else None
+ }
- @Benchmark def traverseFoldRight1: Either[Int, Vector[Int]] = traverseFoldRight(xs1)(f)
- @Benchmark def traverseFoldRight2: Either[Int, Vector[Int]] = traverseFoldRight(xs2)(f)
- @Benchmark def traverseFoldRight3: Either[Int, Vector[Int]] = traverseFoldRight(xs3)(f)
- @Benchmark def traverseFoldRight4: Either[Int, Vector[Int]] = traverseFoldRight(xs4)(f)
+ // we just want to force the allocation to level the playing field
+ inner.value
+ }
- @Benchmark def traverseRec1: Either[Int, Vector[Int]] = traverseRec(xs1)(f)
- @Benchmark def traverseRec2: Either[Int, Vector[Int]] = traverseRec(xs2)(f)
- @Benchmark def traverseRec3: Either[Int, Vector[Int]] = traverseRec(xs3)(f)
- @Benchmark def traverseRec4: Either[Int, Vector[Int]] = traverseRec(xs4)(f)
+ bh.consume(results)
+ }
- @Benchmark def traverseIter1: Either[Int, Vector[Int]] = traverseIter(xs1)(f)
- @Benchmark def traverseIter2: Either[Int, Vector[Int]] = traverseIter(xs2)(f)
- @Benchmark def traverseIter3: Either[Int, Vector[Int]] = traverseIter(xs3)(f)
- @Benchmark def traverseIter4: Either[Int, Vector[Int]] = traverseIter(xs4)(f)
+ @Benchmark
+ def traverseChain(bh: Blackhole) = {
+ val result = chainT.traverse(chain) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+ i * 2
+ }
+ }
- @Benchmark def traverseFoldRightViaList1: Either[Int, Vector[Int]] = traverseFoldRightViaList(xs1)(f)
- @Benchmark def traverseFoldRightViaList2: Either[Int, Vector[Int]] = traverseFoldRightViaList(xs2)(f)
- @Benchmark def traverseFoldRightViaList3: Either[Int, Vector[Int]] = traverseFoldRightViaList(xs3)(f)
- @Benchmark def traverseFoldRightViaList4: Either[Int, Vector[Int]] = traverseFoldRightViaList(xs4)(f)
+ bh.consume(result.value)
+ }
- @Benchmark def traverseRecViaList1: Either[Int, Vector[Int]] = traverseRecViaList(xs1)(f)
- @Benchmark def traverseRecViaList2: Either[Int, Vector[Int]] = traverseRecViaList(xs2)(f)
- @Benchmark def traverseRecViaList3: Either[Int, Vector[Int]] = traverseRecViaList(xs3)(f)
- @Benchmark def traverseRecViaList4: Either[Int, Vector[Int]] = traverseRecViaList(xs4)(f)
+ // TODO: consider renaming to `traverseVoidChain`
+ @Benchmark
+ def traverse_Chain(bh: Blackhole): Unit = {
+ val result = chainT.traverseVoid(chain) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+ i * 2
+ }
+ }
+
+ bh.consume(result.value)
+ }
+
+ @Benchmark
+ def traverseChainError(bh: Blackhole) = {
+ val result = chainT.traverse(chain) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+
+ if (i == length * 0.3) {
+ throw Failure
+ }
+
+ i * 2
+ }
+ }
+
+ try {
+ bh.consume(result.value)
+ } catch {
+ case Failure => ()
+ }
+ }
- @Benchmark def traverseIterViaList1: Either[Int, Vector[Int]] = traverseIterViaList(xs1)(f)
- @Benchmark def traverseIterViaList2: Either[Int, Vector[Int]] = traverseIterViaList(xs2)(f)
- @Benchmark def traverseIterViaList3: Either[Int, Vector[Int]] = traverseIterViaList(xs3)(f)
- @Benchmark def traverseIterViaList4: Either[Int, Vector[Int]] = traverseIterViaList(xs4)(f)
+ @Benchmark
+ def traverseFilterChain(bh: Blackhole) = {
+ val result = chainTFilter.traverseFilter(chain) { i =>
+ Eval.later {
+ Blackhole.consumeCPU(Work)
+ if (i % 2 == 0) Some(i * 2) else None
+ }
+ }
+
+ bh.consume(result.value)
+ }
}
diff --git a/bench/src/main/scala/cats/bench/UnorderedTraverseMapBench.scala b/bench/src/main/scala/cats/bench/UnorderedTraverseMapBench.scala
new file mode 100644
index 0000000000..cf99d271fa
--- /dev/null
+++ b/bench/src/main/scala/cats/bench/UnorderedTraverseMapBench.scala
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.bench
+
+import org.openjdk.jmh.annotations._
+import cats.{CommutativeApplicative, Eval, UnorderedTraverse}
+import java.util.concurrent.TimeUnit
+import cats.data.Chain
+
+@State(Scope.Benchmark)
+@BenchmarkMode(Array(Mode.AverageTime))
+@OutputTimeUnit(TimeUnit.MICROSECONDS)
+class UnorderedTraverseMapBench {
+ // These benchmarks were written to choose the fastest implementation
+ // for Map.unorderedTraverse, some results are available here:
+ // https://github.com/typelevel/cats/pull/4463#issuecomment-1599612154
+
+ val instance = UnorderedTraverse[Map[Int, *]]
+
+ val xs1: Map[Int, Int] = (1 to 1000).map(x => (x, x)).toMap
+ val xs2: Map[Int, Int] = (1 to 1000000).map(x => (x, x)).toMap
+
+ def unorderedTraverseViaTree[G[_], A, B](
+ fa: Map[Int, A]
+ )(f: A => G[B])(implicit G: CommutativeApplicative[G]): G[Map[Int, B]] = {
+ def runHalf(size: Int, fa: Map[Int, A]): Eval[G[Map[Int, B]]] =
+ if (size > 1) {
+ val leftSize = size / 2
+ val rightSize = size - leftSize
+ val (leftL, rightL) = fa.splitAt(leftSize)
+ runHalf(leftSize, leftL).flatMap { left =>
+ val right = runHalf(rightSize, rightL)
+ G.map2Eval(left, right) { (lm, rm) => lm ++ rm }
+ }
+ } else {
+ val (k, a) = fa.head
+ Eval.always(G.map(f(a))(b => Map(k -> b)))
+ }
+
+ val len = fa.size
+ if (len == 0) G.pure(Map.empty)
+ else runHalf(len, fa).value
+ }
+
+ def unorderedTraverseViaChain[G[_], A, B](
+ fa: Map[Int, A]
+ )(f: A => G[B])(implicit G: CommutativeApplicative[G]): G[Map[Int, B]] = {
+ if (fa.isEmpty) G.pure(Map.empty[Int, B])
+ else
+ G.map(Chain.traverseViaChain(fa.toIndexedSeq) { case (k, a) =>
+ G.map(f(a))((k, _))
+ })(_.iterator.toMap)
+ }
+
+ @Benchmark def unorderedTraverseTupleViaTree1: (Int, Map[Int, Int]) =
+ unorderedTraverseViaTree(xs1)(x => (x, x))
+ @Benchmark def unorderedTraverseTupleViaChain1: (Int, Map[Int, Int]) =
+ unorderedTraverseViaChain(xs1)(x => (x, x))
+
+ @Benchmark def unorderedTraverseTupleViaTree2: (Int, Map[Int, Int]) =
+ unorderedTraverseViaTree(xs2)(x => (x, x))
+ @Benchmark def unorderedTraverseTupleViaChain2: (Int, Map[Int, Int]) =
+ unorderedTraverseViaChain(xs2)(x => (x, x))
+
+}
diff --git a/bench/src/main/scala/cats/bench/ValidatedBench.scala b/bench/src/main/scala/cats/bench/ValidatedBench.scala
index 4bd9f0f090..1637c86f59 100644
--- a/bench/src/main/scala/cats/bench/ValidatedBench.scala
+++ b/bench/src/main/scala/cats/bench/ValidatedBench.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.bench
import cats.data.Validated
diff --git a/binCompatTest/src/main/scala/catsBC/MimaExceptions.scala b/binCompatTest/src/main/scala-2/catsBC/MimaExceptions.scala
similarity index 59%
rename from binCompatTest/src/main/scala/catsBC/MimaExceptions.scala
rename to binCompatTest/src/main/scala-2/catsBC/MimaExceptions.scala
index 03ac4d7045..bbfadaf8c6 100644
--- a/binCompatTest/src/main/scala/catsBC/MimaExceptions.scala
+++ b/binCompatTest/src/main/scala-2/catsBC/MimaExceptions.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package catsBC
import cats.InjectK
import cats.implicits._
diff --git a/binCompatTest/src/test/scala-2/catsBC/MimaExceptionsTest.scala b/binCompatTest/src/test/scala-2/catsBC/MimaExceptionsTest.scala
new file mode 100644
index 0000000000..f9dd4d9987
--- /dev/null
+++ b/binCompatTest/src/test/scala-2/catsBC/MimaExceptionsTest.scala
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package catsBC
+
+import munit.FunSuite
+
+class MimaExceptionsTest extends FunSuite {
+ test("is binary compatible") {
+ MimaExceptions.isBinaryCompatible
+ }
+}
diff --git a/binCompatTest/src/test/scala/catsBC/MimaExceptionsTest.scala b/binCompatTest/src/test/scala/catsBC/MimaExceptionsTest.scala
deleted file mode 100644
index 8864f3a030..0000000000
--- a/binCompatTest/src/test/scala/catsBC/MimaExceptionsTest.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package catsBC
-
-import munit.FunSuite
-
-class MimaExceptionsTest extends FunSuite {
- test("is binary compatible") {
- MimaExceptions.isBinaryCompatible
- }
-}
diff --git a/build.sbt b/build.sbt
index d80d5d083d..3d7293d477 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,99 +1,27 @@
-import com.jsuereth.sbtpgp.PgpKeys
-import microsites._
-import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType}
-import sbtrelease.ReleasePlugin.autoImport.ReleaseTransformations._
+ThisBuild / tlBaseVersion := "2.12"
-val isDotty = Def.setting(
- CrossVersion.partialVersion(scalaVersion.value).exists(_._1 == 3)
-)
-
-lazy val publishSignedIfRelevant = taskKey[Unit]("Runs publishSigned but only if scalaVersion in crossScalaVersions")
-Global / publishSignedIfRelevant := PgpKeys.publishSigned.value
-
-lazy val publishLocalSignedIfRelevant =
- taskKey[Unit]("Runs publishLocalSigned but only if scalaVersion in crossScalaVersions")
-Global / publishLocalSignedIfRelevant := PgpKeys.publishLocalSigned.value
-
-ThisBuild / organization := "org.typelevel"
-ThisBuild / scalafixDependencies += "org.typelevel" %% "simulacrum-scalafix" % "0.5.3"
-
-val scalaCheckVersion = "1.15.4"
-
-val disciplineVersion = "1.2.0"
+val scalaCheckVersion = "1.18.1"
-val disciplineMunitVersion = "1.0.9"
+val disciplineVersion = "1.7.0"
-val kindProjectorVersion = "0.13.2"
+val disciplineMunitVersion = "2.0.0"
-ThisBuild / githubWorkflowUseSbtThinClient := false
+val munitVersion = "1.0.4"
-val PrimaryOS = "ubuntu-latest"
-ThisBuild / githubWorkflowOSes := Seq(PrimaryOS)
-ThisBuild / githubWorkflowEnv += ("JABBA_INDEX" -> "https://github.com/typelevel/jdk-index/raw/main/index.json")
+val PrimaryJava = JavaSpec.temurin("8")
+val LTSJava = JavaSpec.temurin("17")
+val GraalVM = JavaSpec.graalvm("21")
-val PrimaryJava = "adoptium@8"
-val LTSJava = "adoptium@17"
-val GraalVM8 = "graalvm-ce-java8@21.2"
+ThisBuild / githubWorkflowJavaVersions := Seq(PrimaryJava, LTSJava, GraalVM)
-ThisBuild / githubWorkflowJavaVersions := Seq(PrimaryJava, LTSJava, GraalVM8)
-
-val Scala212 = "2.12.15"
-val Scala213 = "2.13.7"
-val Scala3 = "3.0.2"
+val Scala212 = "2.12.20"
+val Scala213 = "2.13.16"
+val Scala3 = "3.3.4"
ThisBuild / crossScalaVersions := Seq(Scala212, Scala213, Scala3)
ThisBuild / scalaVersion := Scala213
-ThisBuild / versionScheme := Some("semver-spec")
-
-ThisBuild / githubWorkflowPublishTargetBranches := Seq() // disable publication for now
-
-ThisBuild / githubWorkflowBuildMatrixAdditions +=
- "platform" -> List("jvm", "js", "native")
-ThisBuild / githubWorkflowBuildMatrixExclusions ++=
- githubWorkflowJavaVersions.value.filterNot(Set(PrimaryJava)).flatMap { java =>
- Seq(MatrixExclude(Map("platform" -> "js", "java" -> java)),
- MatrixExclude(Map("platform" -> "native", "java" -> java))
- )
- }
-
-ThisBuild / githubWorkflowBuildMatrixExclusions +=
- MatrixExclude(Map("platform" -> "native", "scala" -> Scala3))
-// Dotty is not yet supported by Scala Native
-
-// we don't need this since we aren't publishing
-ThisBuild / githubWorkflowArtifactUpload := false
-
-val JvmCond = s"matrix.platform == 'jvm'"
-val JsCond = s"matrix.platform == 'js'"
-val NativeCond = s"matrix.platform == 'native'"
-
-val Scala2Cond = s"(matrix.scala != '$Scala3')"
-val Scala3Cond = s"(matrix.scala == '$Scala3')"
-
-ThisBuild / githubWorkflowBuild := Seq(
- WorkflowStep.Sbt(List("validateAllJS"), name = Some("Validate JavaScript"), cond = Some(JsCond))
-) ++
- // this has to be split up to avoid memory issues in GitHub Actions
- validateAllNativeAlias.split(" ").filterNot(_ == "all").map { cmd =>
- val name = cmd.flatMap(c => if (c.isUpper) s" $c" else c.toString).capitalize.replaceAll("/test", "")
- WorkflowStep.Sbt(List(cmd), name = Some(s"Validate $name"), cond = Some(NativeCond))
- } ++
- Seq(
- WorkflowStep.Sbt(List("buildJVM", "bench/test"),
- name = Some("Validate JVM (scala 2)"),
- cond = Some(JvmCond + " && " + Scala2Cond)
- ),
- WorkflowStep.Sbt(List("buildJVM", "bench/test"),
- name = Some("Validate JVM (scala 3)"),
- cond = Some(JvmCond + " && " + Scala3Cond)
- ),
- WorkflowStep.Sbt(
- List("clean", "validateBC"), // cleaning here to avoid issues with codecov
- name = Some("Binary compatibility ${{ matrix.scala }}"),
- cond = Some(JvmCond + " && " + Scala2Cond)
- )
- )
+ThisBuild / tlFatalWarnings := false
ThisBuild / githubWorkflowAddedJobs ++= Seq(
WorkflowJob(
@@ -103,131 +31,49 @@ ThisBuild / githubWorkflowAddedJobs ++= Seq(
WorkflowStep.Run(List("cd scalafix", "sbt test"), name = Some("Scalafix tests"))
),
javas = List(PrimaryJava),
- scalas = crossScalaVersions.value.toList
- ),
- WorkflowJob(
- "linting",
- "Linting",
- githubWorkflowJobSetup.value.toList ::: List(
- WorkflowStep.Sbt(List("fmtCheck"), name = Some("Check formatting"), cond = Some(Scala2Cond))
- ),
- javas = List(PrimaryJava),
- scalas = crossScalaVersions.value.toList
- ),
- WorkflowJob(
- "microsite",
- "Microsite",
- githubWorkflowJobSetup.value.toList ::: List(
- WorkflowStep.Use(UseRef.Public("ruby", "setup-ruby", "v1"),
- params = Map("ruby-version" -> "2.7"),
- name = Some("Setup Ruby")
- ),
- WorkflowStep.Run(List("gem install jekyll -v 4.0.0"), name = Some("Setup Jekyll")),
- WorkflowStep.Sbt(List("docs/makeMicrosite"), name = Some("Build the microsite"))
- ),
- javas = List(PrimaryJava),
- scalas = List(Scala212)
+ scalas = Nil
)
)
-def scalaVersionSpecificFolders(srcName: String, srcBaseDir: java.io.File, scalaVersion: String) = {
- def extraDirs(suffix: String) =
- List(CrossType.Pure, CrossType.Full)
- .flatMap(_.sharedSrcDir(srcBaseDir, srcName).toList.map(f => file(f.getPath + suffix)))
- CrossVersion.partialVersion(scalaVersion) match {
- case Some((2, y)) => extraDirs("-2.x") ++ (if (y >= 13) extraDirs("-2.13+") else Nil)
- case Some((0 | 3, _)) => extraDirs("-2.13+") ++ extraDirs("-3.x")
- case _ => Nil
- }
-}
-
-ThisBuild / mimaFailOnNoPrevious := false
-
-def doctestGenTestsDottyCompat(isDotty: Boolean, genTests: Seq[File]): Seq[File] =
- if (isDotty) Nil else genTests
-
-lazy val commonSettings = Seq(
- scalacOptions ++= commonScalacOptions(scalaVersion.value, isDotty.value),
- Compile / unmanagedSourceDirectories ++= scalaVersionSpecificFolders("main", baseDirectory.value, scalaVersion.value),
- Test / unmanagedSourceDirectories ++= scalaVersionSpecificFolders("test", baseDirectory.value, scalaVersion.value),
- resolvers ++= Seq(Resolver.sonatypeRepo("releases"), Resolver.sonatypeRepo("snapshots")),
- Test / parallelExecution := false,
- testFrameworks += new TestFramework("munit.Framework"),
- Compile / doc / scalacOptions := (Compile / doc / scalacOptions).value.filter(_ != "-Xfatal-warnings")
-) ++ warnUnusedImport
-
-def macroDependencies(scalaVersion: String) =
- if (scalaVersion.startsWith("2")) Seq("org.scala-lang" % "scala-reflect" % scalaVersion % Provided) else Nil
-
-lazy val catsSettings = Seq(
- incOptions := incOptions.value.withLogRecompileOnMacro(false),
- libraryDependencies ++= (
- if (isDotty.value) Nil
+lazy val macroSettings = Seq(
+ libraryDependencies ++= {
+ if (tlIsScala3.value)
+ Nil
else
- Seq(
- compilerPlugin(("org.typelevel" %% "kind-projector" % kindProjectorVersion).cross(CrossVersion.full))
- )
- ) ++ macroDependencies(scalaVersion.value)
-) ++ commonSettings ++ publishSettings ++ simulacrumSettings
+ Seq("org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided)
+ }
+)
-lazy val simulacrumSettings = Seq(
- libraryDependencies ++= (if (isDotty.value) Nil else Seq(compilerPlugin(scalafixSemanticdb))),
- scalacOptions ++= (
- if (isDotty.value) Nil else Seq(s"-P:semanticdb:targetroot:${baseDirectory.value}/target/.semanticdb", "-Yrangepos")
- ),
- libraryDependencies += "org.typelevel" %% "simulacrum-scalafix-annotations" % "0.5.4"
+lazy val cats1BincompatSettings = Seq(
+ tlMimaPreviousVersions ++= {
+ if (scalaVersion.value.startsWith("2.12")) Set("1.0.1", "1.1.0", "1.2.0", "1.3.1", "1.4.0", "1.5.0", "1.6.1")
+ else Set.empty
+ }
)
-lazy val tagName = Def.setting {
- s"v${if (releaseUseGlobalVersion.value) (ThisBuild / version).value else version.value}"
-}
+ThisBuild / tlVersionIntroduced := Map("3" -> "2.6.1")
-lazy val commonJsSettings = Seq(
- publishConfiguration := publishConfiguration.value.withOverwrite(true), // needed since we double-publish on release
- scalacOptions += {
- val tv = tagName.value
- val tagOrHash =
- if (isSnapshot.value) sys.process.Process("git rev-parse HEAD").lineStream_!.head
- else tv
- val a = (LocalRootProject / baseDirectory).value.toURI.toString
- val g = "https://raw.githubusercontent.com/typelevel/cats/" + tagOrHash
- val opt = if (isDotty.value) "-scalajs-mapSourceURI" else "-P:scalajs:mapSourceURI"
- s"$opt:$a->$g/"
- },
- Global / scalaJSStage := FullOptStage,
- Test / scalaJSStage := FastOptStage,
- parallelExecution := false,
- jsEnv := new org.scalajs.jsenv.nodejs.NodeJSEnv(),
- // batch mode decreases the amount of memory needed to compile Scala.js code
- scalaJSLinkerConfig := scalaJSLinkerConfig.value.withBatchMode(githubIsWorkflowBuild.value),
- scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule)),
- // currently sbt-doctest doesn't work in JS builds
- // https://github.com/tkawachi/sbt-doctest/issues/52
- doctestGenTests := Seq.empty
+lazy val commonJvmSettings = Seq(
+ Test / fork := true,
+ Test / javaOptions := Seq("-Xmx3G"),
+ doctestGenTests := { if (tlIsScala3.value) Nil else doctestGenTests.value }
)
-lazy val commonNativeSettings = Seq(
- publishConfiguration := publishConfiguration.value.withOverwrite(true), // needed since we double-publish on release
- // currently sbt-doctest doesn't work in Native/JS builds
- // https://github.com/tkawachi/sbt-doctest/issues/52
+lazy val commonJsSettings = Seq(
doctestGenTests := Seq.empty,
- // Currently scala-native does not support Dotty
- crossScalaVersions := { crossScalaVersions.value.filterNot(Scala3 == _) }
+ tlVersionIntroduced ++= List("2.12", "2.13").map(_ -> "2.1.0").toMap
)
-lazy val commonJvmSettings = Seq(
- Test / fork := true,
- Test / javaOptions := Seq("-Xmx3G")
-)
+Global / concurrentRestrictions += Tags.limit(NativeTags.Link, 1)
-lazy val includeGeneratedSrc: Setting[_] = {
- Compile / packageSrc / mappings ++= {
- val base = (Compile / sourceManaged).value
- (Compile / managedSources).value.map { file =>
- file -> file.relativeTo(base).get.getPath
- }
- }
-}
+// Cats 2.12.0 switches to Scala Native 0.5.
+// Therefore `tlVersionIntroduced` should be reset to 2.12.0 for all scala versions in all native cross-projects.
+val commonNativeTlVersionIntroduced = List("2.12", "2.13", "3").map(_ -> "2.12.0").toMap
+
+lazy val commonNativeSettings = Seq[Setting[?]](
+ doctestGenTests := Seq.empty,
+ tlVersionIntroduced := commonNativeTlVersionIntroduced
+)
lazy val disciplineDependencies = Seq(
libraryDependencies ++= Seq(
@@ -237,565 +83,128 @@ lazy val disciplineDependencies = Seq(
lazy val testingDependencies = Seq(
libraryDependencies ++= Seq(
+ "org.scalameta" %%% "munit" % munitVersion % Test,
"org.typelevel" %%% "discipline-munit" % disciplineMunitVersion % Test
)
)
-lazy val docsMappingsAPIDir = settingKey[String]("Name of subdirectory in site target directory for api docs")
-
-lazy val docSettings = Seq(
- micrositeName := "Cats",
- micrositeDescription := "Lightweight, modular, and extensible library for functional programming",
- micrositeAuthor := "Cats contributors",
- micrositeFooterText := Some(
- """
- |© 2020 The Cats Maintainers
- |Website built with sbt-microsites © 2020 47 Degrees
- |""".stripMargin
- ),
- micrositeHighlightTheme := "atom-one-light",
- micrositeHomepage := "http://typelevel.org/cats/",
- micrositeBaseUrl := "cats",
- micrositeDocumentationUrl := "/cats/api/cats/index.html",
- micrositeDocumentationLabelDescription := "API Documentation",
- micrositeGithubOwner := "typelevel",
- micrositeExtraMdFilesOutput := resourceManaged.value / "main" / "jekyll",
- micrositeExtraMdFiles := Map(
- file("CONTRIBUTING.md") -> ExtraMdFileConfig(
- "contributing.md",
- "home",
- Map("title" -> "Contributing", "section" -> "contributing", "position" -> "50")
- ),
- file("README.md") -> ExtraMdFileConfig(
- "index.md",
- "home",
- Map("title" -> "Home", "section" -> "home", "position" -> "0")
- )
- ),
- micrositeGithubRepo := "cats",
- micrositeImgDirectory := (LocalRootProject / baseDirectory).value / "docs" / "src" / "main" / "resources" / "microsite" / "img",
- micrositeJsDirectory := (LocalRootProject / baseDirectory).value / "docs" / "src" / "main" / "resources" / "microsite" / "js",
- micrositeTheme := "pattern",
- micrositePalette := Map(
- "brand-primary" -> "#5B5988",
- "brand-secondary" -> "#292E53",
- "brand-tertiary" -> "#222749",
- "gray-dark" -> "#49494B",
- "gray" -> "#7B7B7E",
- "gray-light" -> "#E5E5E6",
- "gray-lighter" -> "#F4F3F4",
- "white-color" -> "#FFFFFF"
- ),
- autoAPIMappings := true,
- ScalaUnidoc / unidoc / unidocProjectFilter := inProjects(kernel.jvm, core.jvm, free.jvm),
- docsMappingsAPIDir := "api",
- addMappingsToSiteDir(ScalaUnidoc / packageDoc / mappings, docsMappingsAPIDir),
- ghpagesNoJekyll := false,
- mdoc / fork := true,
- ScalaUnidoc / unidoc / fork := true,
- ScalaUnidoc / unidoc / scalacOptions ++= Seq(
- "-Xfatal-warnings",
- "-groups",
- "-doc-source-url",
- scmInfo.value.get.browseUrl + "/tree/main€{FILE_PATH}.scala",
- "-sourcepath",
- (LocalRootProject / baseDirectory).value.getAbsolutePath,
- "-diagrams"
- ) ++ (if (priorTo2_13(scalaVersion.value))
- Seq("-Yno-adapted-args")
- else
- Nil),
- scalacOptions ~= (_.filterNot(
- Set("-Ywarn-unused-import", "-Ywarn-unused:imports", "-Ywarn-dead-code", "-Xfatal-warnings")
- )),
- git.remoteRepo := "git@github.com:typelevel/cats.git",
- makeSite / includeFilter := "*.html" | "*.css" | "*.png" | "*.jpg" | "*.gif" | "*.js" | "*.swf" | "*.yml" | "*.md" | "*.svg",
- Jekyll / includeFilter := (makeSite / includeFilter).value,
- mdocIn := (LocalRootProject / baseDirectory).value / "docs" / "src" / "main" / "mdoc",
- mdocExtraArguments := Seq("--no-link-hygiene")
-)
-
-def mimaPrevious(moduleName: String, scalaVer: String, ver: String, includeCats1: Boolean = true): List[ModuleID] = {
- import sbtrelease.Version
-
- def semverBinCompatVersions(major: Int, minor: Int, patch: Int): List[(Int, Int, Int)] = {
- val majorVersions: List[Int] = List(major)
- val minorVersions: List[Int] =
- if (major >= 1) Range(0, minor).inclusive.toList
- else List(minor)
- def patchVersions(currentMinVersion: Int): List[Int] =
- if (minor == 0 && patch == 0) List.empty[Int]
- else if (currentMinVersion != minor) List(0)
- else Range(0, patch - 1).inclusive.toList
-
- for {
- maj <- majorVersions
- min <- minorVersions
- pat <- patchVersions(min)
- } yield (maj, min, pat)
- }
-
- val mimaVersions: List[String] = {
- Version(ver) match {
- case Some(Version(major, Seq(minor, patch), _)) =>
- semverBinCompatVersions(major, minor, patch)
- .map { case (maj, min, pat) => s"$maj.$min.$pat" }
- case _ =>
- List.empty[String]
- }
- }
- // Safety Net For Exclusions
- lazy val excludedVersions: List[String] = List()
-
- // Safety Net for Inclusions
- lazy val extraVersions: List[String] = List("1.0.1", "1.1.0", "1.2.0", "1.3.1", "1.4.0", "1.5.0", "1.6.1")
-
- (mimaVersions ++ (if (priorTo2_13(scalaVer) && includeCats1) extraVersions else Nil))
- .filterNot(excludedVersions.contains(_))
- .map(v => "org.typelevel" %% moduleName % v)
-}
-
-def mimaSettings(moduleName: String, includeCats1: Boolean = true) =
- Seq(
- mimaPreviousArtifacts := mimaPrevious(moduleName, scalaVersion.value, version.value, includeCats1).toSet,
- mimaBinaryIssueFilters ++= {
- import com.typesafe.tools.mima.core.ProblemFilters._
- import com.typesafe.tools.mima.core._
- // Only sealed abstract classes that provide implicit instances to companion objects are allowed here, since they don't affect usage outside of the file.
- Seq(
- exclude[DirectMissingMethodProblem]("cats.data.OptionTInstances2.catsDataTraverseForOptionT"),
- exclude[DirectMissingMethodProblem]("cats.data.KleisliInstances1.catsDataCommutativeArrowForKleisliId"),
- exclude[DirectMissingMethodProblem]("cats.data.OptionTInstances1.catsDataMonoidKForOptionT"),
- exclude[DirectMissingMethodProblem]("cats.data.OptionTInstances0.catsDataMonoidForOptionT"),
- exclude[DirectMissingMethodProblem]("cats.data.KleisliInstances0.catsDataMonadForKleisliId"),
- exclude[DirectMissingMethodProblem]("cats.data.KleisliInstances1.catsDataCommutativeArrowForKleisli"),
- exclude[DirectMissingMethodProblem]("cats.data.KleisliInstances4.catsDataCommutativeFlatMapForKleisli"),
- exclude[DirectMissingMethodProblem]("cats.data.IRWSTInstances1.catsDataStrongForIRWST"),
- exclude[DirectMissingMethodProblem]("cats.data.OptionTInstances1.catsDataMonadErrorMonadForOptionT"),
- exclude[DirectMissingMethodProblem]("cats.data.OptionTInstances1.catsDataMonadErrorForOptionT")
- ) ++
- // These things are Ops classes that shouldn't have the `value` exposed. These should have never been public because they don't
- // provide any value. Making them private because of issues like #2514 and #2613.
- Seq(
- exclude[DirectMissingMethodProblem]("cats.ApplicativeError#LiftFromOptionPartially.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.Const#OfPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.EitherT#CondPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.EitherT#FromEitherPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.EitherT#FromOptionPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.EitherT#LeftPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.EitherT#LeftTPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.EitherT#PurePartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.EitherT#RightPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.IorT#BothTPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.IorT#CondPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.IorT#FromEitherPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.IorT#FromIorPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.IorT#FromOptionPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.IorT#LeftPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.IorT#LeftTPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.IorT#PurePartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.IorT#RightPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.NonEmptyChainOps.value"),
- exclude[DirectMissingMethodProblem]("cats.data.OptionT#FromOptionPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.OptionT#PurePartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.data.Validated#CatchOnlyPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.free.Free#FreeInjectKPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.free.Free#FreeLiftInjectKPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.free.FreeT#FreeTLiftInjectKPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ApplicativeErrorIdOps.e"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ApplicativeErrorOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ApplicativeIdOps.a"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ApplicativeOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ApplyOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.BinestedIdOps.value"),
- exclude[DirectMissingMethodProblem]("cats.syntax.BitraverseOps.fab"),
- exclude[DirectMissingMethodProblem]("cats.syntax.DistributiveOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EitherIdOps.obj"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EitherIdOpsBinCompat0.value"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EitherSyntax#CatchOnlyPartiallyApplied.dummy"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EitherKOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EitherObjectOps.either"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EitherOps.eab"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EitherOpsBinCompat0.value"),
- exclude[DirectMissingMethodProblem]("cats.syntax.FlatMapIdOps.a"),
- exclude[DirectMissingMethodProblem]("cats.syntax.FlatMapOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.FlatMapOptionOps.fopta"),
- exclude[DirectMissingMethodProblem]("cats.syntax.FlattenOps.ffa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.FoldableOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.GuardOps.condition"),
- exclude[DirectMissingMethodProblem]("cats.syntax.IfMOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.IndexOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.IorIdOps.a"),
- exclude[DirectMissingMethodProblem]("cats.syntax.LeftOps.left"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ListOps.la"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ListOpsBinCompat0.la"),
- exclude[DirectMissingMethodProblem]("cats.syntax.MonadErrorOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.MonadErrorRethrowOps.fea"),
- exclude[DirectMissingMethodProblem]("cats.syntax.MonadIdOps.a"),
- exclude[DirectMissingMethodProblem]("cats.syntax.MonadOps.fa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.MonoidOps.lhs"),
- exclude[DirectMissingMethodProblem]("cats.syntax.NestedBitraverseOps.fgagb"),
- exclude[DirectMissingMethodProblem]("cats.syntax.NestedFoldableOps.fga"),
- exclude[DirectMissingMethodProblem]("cats.syntax.NestedIdOps.value"),
- exclude[DirectMissingMethodProblem]("cats.syntax.NestedReducibleOps.fga"),
- exclude[DirectMissingMethodProblem]("cats.syntax.OptionIdOps.a"),
- exclude[DirectMissingMethodProblem]("cats.syntax.OptionOps.oa"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ParallelApOps.ma"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ParallelFlatSequenceOps.tmta"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ParallelFlatTraversableOps.ta"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ParallelSequence_Ops.tma"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ParallelSequenceOps.tma"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ParallelTraversable_Ops.ta"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ParallelTraversableOps.ta"),
- exclude[DirectMissingMethodProblem]("cats.syntax.RightOps.right"),
- exclude[DirectMissingMethodProblem]("cats.syntax.SeparateOps.fgab"),
- exclude[DirectMissingMethodProblem]("cats.syntax.SetOps.se"),
- exclude[DirectMissingMethodProblem]("cats.syntax.TabulateOps.f"),
- exclude[DirectMissingMethodProblem]("cats.syntax.TryOps.self"),
- exclude[DirectMissingMethodProblem]("cats.syntax.UniteOps.fga"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ValidatedExtension.self"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ValidatedIdOpsBinCompat0.a"),
- exclude[DirectMissingMethodProblem]("cats.syntax.ValidatedIdSyntax.a"),
- exclude[DirectMissingMethodProblem]("cats.syntax.VectorOps.va"),
- exclude[DirectMissingMethodProblem]("cats.syntax.WriterIdSyntax.a")
- ) ++ // Only compile-time abstractions (macros) allowed here
- Seq(
- exclude[IncompatibleMethTypeProblem]("cats.arrow.FunctionKMacros.lift"),
- exclude[MissingTypesProblem]("cats.arrow.FunctionKMacros$"),
- exclude[IncompatibleMethTypeProblem]("cats.arrow.FunctionKMacros#Lifter.this"),
- exclude[IncompatibleResultTypeProblem]("cats.arrow.FunctionKMacros#Lifter.c"),
- exclude[DirectMissingMethodProblem]("cats.arrow.FunctionKMacros.compatNewTypeName")
- ) ++ // package private classes no longer needed
- Seq(
- exclude[MissingClassProblem]("cats.kernel.compat.scalaVersionMoreSpecific$"),
- exclude[MissingClassProblem]("cats.kernel.compat.scalaVersionMoreSpecific"),
- exclude[MissingClassProblem](
- "cats.kernel.compat.scalaVersionMoreSpecific$suppressUnusedImportWarningForScalaVersionMoreSpecific"
- )
- ) ++ // Only narrowing of types allowed here
- Seq(
- exclude[IncompatibleSignatureProblem]("*")
- ) ++ // New issues found since mima 0.8.0 (#3596, #3641)
- Seq(
- exclude[NewMixinForwarderProblem]("cats.kernel.Band#mcI#sp.combineN"),
- exclude[NewMixinForwarderProblem]("cats.kernel.Band#mcD#sp.combineN"),
- exclude[NewMixinForwarderProblem]("cats.kernel.Band#mcJ#sp.combineN"),
- exclude[NewMixinForwarderProblem]("cats.kernel.Band.combineN"),
- exclude[NewMixinForwarderProblem]("cats.kernel.Band#mcF#sp.combineN"),
- exclude[NewMixinForwarderProblem]("cats.data.Tuple2KApply.product"),
- exclude[NewMixinForwarderProblem]("cats.InvariantInstances0.catsApplicativeForArrow")
- ) ++ // Additional methods in package-private traits
- Seq(
- exclude[ReversedMissingMethodProblem]("cats.data.NonEmptyCollection.grouped")
- ) ++ // https://github.com/typelevel/cats/pull/3785
- Seq(
- exclude[MissingClassProblem]("cats.syntax.EqOps$mcJ$sp"),
- exclude[MissingClassProblem]("cats.syntax.EqOps$mcD$sp"),
- exclude[FinalClassProblem]("cats.syntax.EqOps"),
- exclude[MissingFieldProblem]("cats.syntax.EqOps.lhs"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.unapply"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.apply"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.lhs"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy$default$1"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productPrefix"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productArity"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productElement"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productIterator"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.canEqual"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy$default$1$mcD$sp"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy$default$1$mcF$sp"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy$default$1$mcJ$sp"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy$default$1$mcI$sp"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productElementNames"),
- exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productElementName"),
- exclude[MissingClassProblem]("cats.syntax.EqOps$"),
- exclude[MissingClassProblem]("cats.syntax.EqOps$mcF$sp"),
- exclude[MissingClassProblem]("cats.syntax.EqOps$mcI$sp")
- ) ++ // https://github.com/typelevel/cats/pull/3918
- Seq(
- exclude[MissingClassProblem]("algebra.laws.IsSerializable"),
- exclude[MissingClassProblem]("algebra.laws.IsSerializable$")
- ) ++ // https://github.com/typelevel/cats/pull/3987
- Seq(
- exclude[DirectAbstractMethodProblem]("cats.free.ContravariantCoyoneda.k"),
- exclude[ReversedAbstractMethodProblem]("cats.free.ContravariantCoyoneda.k"),
- exclude[DirectAbstractMethodProblem]("cats.free.Coyoneda.k"),
- exclude[ReversedAbstractMethodProblem]("cats.free.Coyoneda.k")
- )
- }
- )
-
-lazy val docs = project
- .in(file("cats-docs"))
- .enablePlugins(MdocPlugin)
- .enablePlugins(MicrositesPlugin)
- .enablePlugins(ScalaUnidocPlugin)
- .settings(moduleName := "cats-docs")
- .settings(catsSettings)
- .settings(noPublishSettings)
- .settings(docSettings)
- .settings(commonJvmSettings)
- .settings(
- libraryDependencies ++= Seq(
- "org.typelevel" %%% "discipline-munit" % disciplineMunitVersion
- ),
- ScalaUnidoc / unidoc / scalacOptions ~= (_.filter(_ != "-Xlint:-unused,_"))
- )
- .dependsOn(core.jvm, free.jvm, kernelLaws.jvm, laws.jvm)
-
-lazy val cats = project
- .in(file("."))
- .settings(moduleName := "root")
- .settings(publishSettings) // these settings are needed to release all aggregated modules under this root module
- .settings(noPublishSettings) // this is to exclude the root module itself from being published.
- .aggregate(catsJVM, catsJS, catsNative)
- .dependsOn(catsJVM, catsJS, catsNative, tests.jvm % "test-internal -> test")
-
-lazy val catsJVM = project
- .in(file(".catsJVM"))
- .settings(moduleName := "cats")
- .settings(noPublishSettings)
- .settings(catsSettings)
- .settings(commonJvmSettings)
- .aggregate(
- kernel.jvm,
- kernelLaws.jvm,
- algebra.jvm,
- algebraLaws.jvm,
- core.jvm,
- laws.jvm,
- free.jvm,
- testkit.jvm,
- tests.jvm,
- alleycatsCore.jvm,
- alleycatsLaws.jvm,
- alleycatsTests.jvm,
- jvm
- )
- .dependsOn(
- kernel.jvm,
- kernelLaws.jvm,
- algebra.jvm,
- algebraLaws.jvm,
- core.jvm,
- laws.jvm,
- free.jvm,
- testkit.jvm,
- tests.jvm % "test-internal -> test",
- alleycatsCore.jvm,
- alleycatsLaws.jvm,
- alleycatsTests.jvm % "test-internal -> test",
- jvm
- )
-
-lazy val catsJS = project
- .in(file(".catsJS"))
- .settings(moduleName := "cats")
- .settings(noPublishSettings)
- .settings(catsSettings)
- .settings(commonJsSettings)
- .aggregate(kernel.js,
- kernelLaws.js,
- algebra.js,
- algebraLaws.js,
- core.js,
- laws.js,
- free.js,
- testkit.js,
- tests.js,
- alleycatsCore.js,
- alleycatsLaws.js,
- alleycatsTests.js,
- js
- )
- .dependsOn(
- kernel.js,
- kernelLaws.js,
- algebra.js,
- algebraLaws.js,
- core.js,
- laws.js,
- free.js,
- testkit.js,
- tests.js % "test-internal -> test",
- alleycatsCore.js,
- alleycatsLaws.js,
- alleycatsTests.js % "test-internal -> test",
- js
- )
- .enablePlugins(ScalaJSPlugin)
-
-lazy val catsNative = project
- .in(file(".catsNative"))
- .settings(moduleName := "cats")
- .settings(noPublishSettings)
- .settings(catsSettings)
- .settings(commonNativeSettings)
+lazy val cats = tlCrossRootProject
.aggregate(
- kernel.native,
- kernelLaws.native,
- algebra.native,
- algebraLaws.native,
- core.native,
- laws.native,
- free.native,
- testkit.native,
- tests.native,
- alleycatsCore.native,
- alleycatsLaws.native,
- alleycatsTests.native,
- native
+ kernel,
+ kernelLaws,
+ algebra,
+ algebraLaws,
+ core,
+ laws,
+ free,
+ testkit,
+ tests,
+ alleycatsCore,
+ alleycatsLaws,
+ unidocs,
+ bench,
+ binCompatTest
)
- .dependsOn(
- kernel.native,
- kernelLaws.native,
- algebra.native,
- algebraLaws.native,
- core.native,
- laws.native,
- free.native,
- testkit.native,
- tests.native % "test-internal -> test",
- alleycatsCore.native,
- alleycatsLaws.native,
- alleycatsTests.native % "test-internal -> test",
- native
- )
- .enablePlugins(ScalaNativePlugin)
lazy val kernel = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.crossType(CrossType.Pure)
.in(file("kernel"))
.settings(moduleName := "cats-kernel", name := "Cats kernel")
- .settings(commonSettings)
- .settings(publishSettings)
+ .settings(testingDependencies)
.settings(Compile / sourceGenerators += (Compile / sourceManaged).map(KernelBoiler.gen).taskValue)
- .settings(includeGeneratedSrc)
.jsSettings(commonJsSettings)
- .jvmSettings(commonJvmSettings ++ mimaSettings("cats-kernel"))
+ .jvmSettings(commonJvmSettings, cats1BincompatSettings)
.nativeSettings(commonNativeSettings)
- .settings(testingDependencies)
- .settings(
- libraryDependencies += "org.scalacheck" %%% "scalacheck" % scalaCheckVersion % Test
- )
lazy val kernelLaws = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.in(file("kernel-laws"))
+ .dependsOn(kernel)
.settings(moduleName := "cats-kernel-laws", name := "Cats kernel laws")
- .settings(commonSettings)
- .settings(publishSettings)
.settings(disciplineDependencies)
.settings(testingDependencies)
- .settings(Test / scalacOptions := (Test / scalacOptions).value.filter(_ != "-Xfatal-warnings"))
.jsSettings(commonJsSettings)
- .jvmSettings(commonJvmSettings ++ mimaSettings("cats-kernel-laws", includeCats1 = false))
- .dependsOn(kernel)
+ .jvmSettings(commonJvmSettings)
.nativeSettings(commonNativeSettings)
+lazy val algebraSettings = Seq[Setting[?]](
+ tlMimaPreviousVersions += "2.2.3",
+ tlVersionIntroduced := List("2.12", "2.13", "3").map(_ -> "2.7.0").toMap
+)
+
+lazy val algebraNativeSettings = Seq[Setting[?]](
+ // Reset to auto-populate from `tlVersionIntroduced` below.
+ tlMimaPreviousVersions := Set.empty,
+ // Should be reset to the common setting value, because `algebraSettings` re-defines it.
+ tlVersionIntroduced := commonNativeTlVersionIntroduced
+)
+
lazy val algebra = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.crossType(CrossType.Pure)
.in(file("algebra-core"))
- .settings(moduleName := "algebra", name := "Cats algebra")
.dependsOn(kernel)
- .settings(commonSettings)
- .settings(publishSettings)
+ .settings(moduleName := "algebra", name := "Cats algebra", scalacOptions -= "-Xsource:3")
.settings(Compile / sourceGenerators += (Compile / sourceManaged).map(AlgebraBoilerplate.gen).taskValue)
- .settings(includeGeneratedSrc)
.jsSettings(commonJsSettings)
- .jvmSettings(
- commonJvmSettings ++ mimaSettings("algebra") ++ Seq(
- mimaPreviousArtifacts := Set("org.typelevel" %% "algebra" % "2.2.3")
- )
- )
+ .jvmSettings(commonJvmSettings)
.nativeSettings(commonNativeSettings)
- .settings(testingDependencies)
.settings(
- scalacOptions := {
- if (isDotty.value)
- scalacOptions.value.filterNot(Set("-Xfatal-warnings"))
- else scalacOptions.value
- },
- libraryDependencies += "org.scalacheck" %%% "scalacheck" % scalaCheckVersion % Test
+ algebraSettings,
+ libraryDependencies += "org.scalacheck" %%% "scalacheck" % scalaCheckVersion % Test,
+ testingDependencies
)
+ .nativeSettings(algebraNativeSettings)
lazy val algebraLaws = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.in(file("algebra-laws"))
- .settings(moduleName := "algebra-laws", name := "Cats algebra laws")
- .settings(commonSettings)
- .settings(publishSettings)
+ .dependsOn(kernelLaws, algebra)
+ .settings(moduleName := "algebra-laws", name := "Cats algebra laws", scalacOptions -= "-Xsource:3")
.settings(disciplineDependencies)
.settings(testingDependencies)
- .settings(
- scalacOptions := {
- if (isDotty.value)
- scalacOptions.value.filterNot(Set("-Xfatal-warnings"))
- else scalacOptions.value
- },
- Test / scalacOptions := (Test / scalacOptions).value.filter(_ != "-Xfatal-warnings")
- )
.jsSettings(commonJsSettings)
- .jvmSettings(
- commonJvmSettings ++ mimaSettings("algebra-laws") ++ Seq(
- mimaPreviousArtifacts := Set("org.typelevel" %% "algebra-laws" % "2.2.3")
- )
- )
- .dependsOn(kernelLaws, algebra)
+ .jvmSettings(commonJvmSettings)
.nativeSettings(commonNativeSettings)
+ .settings(algebraSettings)
+ .nativeSettings(algebraNativeSettings)
lazy val core = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.crossType(CrossType.Pure)
.dependsOn(kernel)
.settings(moduleName := "cats-core", name := "Cats core")
- .settings(catsSettings)
+ .settings(macroSettings)
.settings(Compile / sourceGenerators += (Compile / sourceManaged).map(Boilerplate.gen).taskValue)
- .settings(includeGeneratedSrc)
.settings(
- libraryDependencies += "org.scalacheck" %%% "scalacheck" % scalaCheckVersion % Test,
- doctestGenTests := doctestGenTestsDottyCompat(isDotty.value, doctestGenTests.value)
- )
- .settings(
- Compile / scalacOptions :=
- (Compile / scalacOptions).value.filter {
- case "-Xfatal-warnings" if isDotty.value => false
- case _ => true
- }
+ libraryDependencies += "org.scalacheck" %%% "scalacheck" % scalaCheckVersion % Test
)
- .jsSettings(commonJsSettings)
- .jvmSettings(commonJvmSettings ++ mimaSettings("cats-core"))
.settings(testingDependencies)
+ .jsSettings(commonJsSettings)
+ .jvmSettings(commonJvmSettings, cats1BincompatSettings)
.nativeSettings(commonNativeSettings)
lazy val laws = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.crossType(CrossType.Pure)
.dependsOn(kernel, core, kernelLaws)
.settings(moduleName := "cats-laws", name := "Cats laws")
- .settings(catsSettings)
.settings(disciplineDependencies)
.settings(testingDependencies)
.jsSettings(commonJsSettings)
- .jvmSettings(commonJvmSettings ++ mimaSettings("cats-laws", includeCats1 = false))
+ .jvmSettings(commonJvmSettings)
.nativeSettings(commonNativeSettings)
lazy val free = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.crossType(CrossType.Pure)
.dependsOn(core, tests % "test-internal -> test")
.settings(moduleName := "cats-free", name := "Cats Free")
- .settings(catsSettings)
.jsSettings(commonJsSettings)
- .jvmSettings(commonJvmSettings ++ mimaSettings("cats-free"))
+ .jvmSettings(commonJvmSettings, cats1BincompatSettings)
.nativeSettings(commonNativeSettings)
lazy val tests = crossProject(JSPlatform, JVMPlatform, NativePlatform)
- .crossType(CrossType.Pure)
.dependsOn(testkit % Test)
+ .enablePlugins(NoPublishPlugin)
.settings(moduleName := "cats-tests")
- .settings(catsSettings)
- .settings(noPublishSettings)
.settings(testingDependencies)
.jsSettings(commonJsSettings)
.jvmSettings(commonJvmSettings)
- .settings(Test / scalacOptions := (Test / scalacOptions).value.filter(_ != "-Xfatal-warnings"))
.nativeSettings(commonNativeSettings)
lazy val testkit = crossProject(JSPlatform, JVMPlatform, NativePlatform)
@@ -804,11 +213,9 @@ lazy val testkit = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.enablePlugins(BuildInfoPlugin)
.settings(buildInfoKeys := Seq[BuildInfoKey](scalaVersion), buildInfoPackage := "cats.tests")
.settings(moduleName := "cats-testkit")
- .settings(catsSettings)
.settings(disciplineDependencies)
.jsSettings(commonJsSettings)
- .jvmSettings(commonJvmSettings ++ mimaSettings("cats-testkit", includeCats1 = false))
- .settings(scalacOptions := scalacOptions.value.filter(_ != "-Xfatal-warnings"))
+ .jvmSettings(commonJvmSettings)
.nativeSettings(commonNativeSettings)
lazy val alleycatsCore = crossProject(JSPlatform, JVMPlatform, NativePlatform)
@@ -816,312 +223,106 @@ lazy val alleycatsCore = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.in(file("alleycats-core"))
.dependsOn(core)
.settings(moduleName := "alleycats-core", name := "Alleycats core")
- .settings(catsSettings)
- .settings(publishSettings)
- .settings(includeGeneratedSrc)
.jsSettings(commonJsSettings)
- .jvmSettings(commonJvmSettings ++ mimaSettings("alleycats-core", includeCats1 = false))
+ .jvmSettings(commonJvmSettings)
.nativeSettings(commonNativeSettings)
lazy val alleycatsLaws = crossProject(JSPlatform, JVMPlatform, NativePlatform)
- .crossType(CrossType.Pure)
.in(file("alleycats-laws"))
- .dependsOn(alleycatsCore, laws)
+ .dependsOn(alleycatsCore, laws, tests % "test-internal -> test")
.settings(moduleName := "alleycats-laws", name := "Alleycats laws")
- .settings(catsSettings)
- .settings(publishSettings)
.settings(disciplineDependencies)
.settings(testingDependencies)
.jsSettings(commonJsSettings)
- .jvmSettings(commonJvmSettings ++ mimaSettings("alleycats-laws", includeCats1 = false))
- .nativeSettings(commonNativeSettings)
-
-lazy val alleycatsTests = crossProject(JSPlatform, JVMPlatform, NativePlatform)
- .in(file("alleycats-tests"))
- .dependsOn(alleycatsLaws, tests % "test-internal -> test")
- .settings(moduleName := "alleycats-tests")
- .settings(catsSettings)
- .settings(noPublishSettings)
- .jsSettings(commonJsSettings)
.jvmSettings(commonJvmSettings)
- .settings(Test / scalacOptions := (Test / scalacOptions).value.filter(_ != "-Xfatal-warnings"))
.nativeSettings(commonNativeSettings)
+lazy val unidocs = project
+ .enablePlugins(TypelevelUnidocPlugin)
+ .settings(
+ name := "cats-docs",
+ ScalaUnidoc / unidoc / unidocProjectFilter := inProjects(kernel.jvm,
+ kernelLaws.jvm,
+ core.jvm,
+ laws.jvm,
+ free.jvm,
+ algebra.jvm,
+ algebraLaws.jvm,
+ alleycatsCore.jvm,
+ alleycatsLaws.jvm,
+ testkit.jvm
+ ),
+ ScalaUnidoc / unidoc / scalacOptions ++= Seq("-groups", "-diagrams")
+ )
+
// bench is currently JVM-only
lazy val bench = project
.dependsOn(core.jvm, free.jvm, laws.jvm)
.settings(moduleName := "cats-bench")
- .settings(catsSettings)
- .settings(noPublishSettings)
.settings(commonJvmSettings)
.settings(
- libraryDependencies ++= {
- if (priorTo2_13(scalaVersion.value))
- Seq(
- "org.scalaz" %% "scalaz-core" % "7.2.23",
- "org.spire-math" %% "chain" % "0.3.0",
- "co.fs2" %% "fs2-core" % "0.10.4"
- )
- else Nil
- },
evictionErrorLevel := Level.Warn
)
- .enablePlugins(JmhPlugin)
+ .enablePlugins(NoPublishPlugin, JmhPlugin)
lazy val binCompatTest = project
- .settings(noPublishSettings)
+ .enablePlugins(NoPublishPlugin)
.settings(
- // workaround because coursier doesn't understand dependsOn(core.jvm % Test)
- // see https://github.com/typelevel/cats/pull/3079#discussion_r327181584
- // see https://github.com/typelevel/cats/pull/3026#discussion_r321984342
- useCoursier := false,
- addCompilerPlugin(("org.typelevel" %% "kind-projector" % kindProjectorVersion).cross(CrossVersion.full)),
- libraryDependencies += mimaPrevious("cats-core", scalaVersion.value, version.value).last % Provided,
- scalacOptions ++= (if (priorTo2_13(scalaVersion.value)) Seq("-Ypartial-unification") else Nil)
+ useCoursier := false, // workaround so we can use an old version in compile
+ libraryDependencies += {
+ val oldV = if (tlIsScala3.value) "2.6.1" else "2.0.0"
+ "org.typelevel" %%% "cats-core" % oldV % Provided
+ }
)
.settings(testingDependencies)
.dependsOn(core.jvm % Test)
-// cats-js is JS-only
-lazy val js = project
- .dependsOn(core.js, tests.js % "test-internal -> test")
- .settings(moduleName := "cats-js")
- .settings(catsSettings)
- .settings(commonJsSettings)
- .enablePlugins(ScalaJSPlugin)
-
-// cats-native is Native-only
-lazy val native = project
- .dependsOn(core.native, tests.native % "test-internal -> test")
- .settings(moduleName := "cats-native")
- .settings(catsSettings)
- .settings(commonNativeSettings)
- .enablePlugins(ScalaNativePlugin)
-
-// cats-jvm is JVM-only
-lazy val jvm = project
- .dependsOn(core.jvm, tests.jvm % "test-internal -> test")
- .settings(moduleName := "cats-jvm")
- .settings(catsSettings)
- .settings(commonJvmSettings)
-
-lazy val publishSettings = Seq(
- homepage := Some(url("https://github.com/typelevel/cats")),
- licenses := Seq("MIT" -> url("http://opensource.org/licenses/MIT")),
- scmInfo := Some(ScmInfo(url("https://github.com/typelevel/cats"), "scm:git:git@github.com:typelevel/cats.git")),
- autoAPIMappings := true,
- apiURL := Some(url("http://typelevel.org/cats/api/")),
- pomExtra :=
-
-
- ceedubs
- Cody Allen
- https://github.com/ceedubs/
-
-
- rossabaker
- Ross Baker
- https://github.com/rossabaker/
-
-
- johnynek
- P. Oscar Boykin
- https://github.com/johnynek/
-
-
- travisbrown
- Travis Brown
- https://github.com/travisbrown/
-
-
- adelbertc
- Adelbert Chang
- https://github.com/adelbertc/
-
-
- peterneyens
- Peter Neyens
- https://github.com/peterneyens/
-
-
- tpolecat
- Rob Norris
- https://github.com/tpolecat/
-
-
- non
- Erik Osheim
- https://github.com/non/
-
-
- LukaJCB
- LukaJCB
- https://github.com/LukaJCB/
-
-
- mpilquist
- Michael Pilquist
- https://github.com/mpilquist/
-
-
- milessabin
- Miles Sabin
- https://github.com/milessabin/
-
-
- djspiewak
- Daniel Spiewak
- https://github.com/djspiewak/
-
-
- fthomas
- Frank Thomas
- https://github.com/fthomas/
-
-
- julien-truffaut
- Julien Truffaut
- https://github.com/julien-truffaut/
-
-
- kailuowang
- Kailuo Wang
- https://github.com/kailuowang/
-
-
-) ++ sharedPublishSettings ++ sharedReleaseProcess
-
-// Scalafmt
-addCommandAlias("fmt", "; Compile / scalafmt; Test / scalafmt; scalafmtSbt")
-addCommandAlias("fmtCheck", "; Compile / scalafmtCheck; Test / scalafmtCheck; scalafmtSbtCheck")
-
-// These aliases serialise the build for the benefit of Travis-CI.
-addCommandAlias("buildKernelJVM", ";kernelJVM/test;kernelLawsJVM/test")
-addCommandAlias("buildCoreJVM", ";coreJVM/test")
-addCommandAlias("buildTestsJVM", ";lawsJVM/test;testkitJVM/test;testsJVM/test;jvm/test")
-addCommandAlias("buildFreeJVM", ";freeJVM/test")
-addCommandAlias("buildAlleycatsJVM", ";alleycatsCoreJVM/test;alleycatsLawsJVM/test;alleycatsTestsJVM/test")
-addCommandAlias("buildAlgebraJVM", ";algebraJVM/test;algebraLawsJVM/test")
-addCommandAlias("buildJVM", ";buildKernelJVM;buildCoreJVM;buildTestsJVM;buildFreeJVM;buildAlleycatsJVM;buildAlgebraJVM")
-addCommandAlias("validateBC", ";binCompatTest/test;catsJVM/mimaReportBinaryIssues")
-addCommandAlias("validateJVM", ";fmtCheck;buildJVM;bench/test;validateBC;makeMicrosite")
-addCommandAlias("validateJS", ";testsJS/test;js/test")
-addCommandAlias("validateKernelJS", "kernelLawsJS/test")
-addCommandAlias("validateFreeJS", "freeJS/test")
-addCommandAlias("validateAlleycatsJS", "alleycatsTestsJS/test")
-addCommandAlias("validateAlgebraJS", "algebraLawsJS/test")
-addCommandAlias("validateAllJS",
- "all testsJS/test js/test kernelLawsJS/test freeJS/test alleycatsTestsJS/test algebraLawsJS/test"
-)
-addCommandAlias("validateNative", ";testsNative/test;native/test")
-addCommandAlias("validateKernelNative", "kernelLawsNative/test")
-addCommandAlias("validateFreeNative", "freeNative/test")
-addCommandAlias("validateAlleycatsNative", "alleycatsTestsNative/test")
-addCommandAlias("validateAlgebraNative", "algebraLawsNative/test")
-
-val validateAllNativeAlias =
- "all testsNative/test native/test kernelLawsNative/test freeNative/test alleycatsTestsNative/test algebraLawsNative/test"
-addCommandAlias("validateAllNative", validateAllNativeAlias)
-
-addCommandAlias(
- "validate",
- ";clean;validateJS;validateKernelJS;validateFreeJS;validateAlleycatsJS;validateAlgebraJS;validateNative;validateKernelNative;validateFreeNative;validateAlgebraNative;validateJVM"
-)
-
-addCommandAlias("prePR", "fmt")
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Base Build Settings - Should not need to edit below this line.
-// These settings could also come from another file or a plugin.
-// The only issue if coming from a plugin is that the Macro lib versions
-// are hard coded, so an overided facility would be required.
-
-addCommandAlias("gitSnapshots", ";set version in ThisBuild := git.gitDescribedVersion.value.get + \"-SNAPSHOT\"")
-
-lazy val noPublishSettings = Seq(
- publish := {},
- publishLocal := {},
- publishArtifact := false
-)
-
-lazy val crossVersionSharedSources: Seq[Setting[_]] =
- Seq(Compile, Test).map { sc =>
- sc / unmanagedSourceDirectories ++= {
- (sc / unmanagedSourceDirectories).value.map { dir: File =>
- new File(dir.getPath + "_" + scalaBinaryVersion.value)
- }
- }
- }
-
-def commonScalacOptions(scalaVersion: String, isDotty: Boolean) =
- Seq(
- "-encoding",
- "UTF-8",
- "-feature",
- "-unchecked",
- "-Xfatal-warnings",
- "-deprecation"
- ) ++ (if (priorTo2_13(scalaVersion))
- Seq(
- "-Yno-adapted-args",
- "-Ypartial-unification",
- "-Xfuture"
- )
- else
- Nil) ++ (if (isDotty)
- Seq("-language:implicitConversions", "-Ykind-projector", "-Xignore-scala2-macros")
- else
- Seq(
- "-language:existentials",
- "-language:higherKinds",
- "-language:implicitConversions",
- "-Ywarn-dead-code",
- "-Ywarn-numeric-widen",
- "-Ywarn-value-discard",
- "-Xlint:-unused,_"
- ))
-
-def priorTo2_13(scalaVersion: String): Boolean =
- CrossVersion.partialVersion(scalaVersion) match {
- case Some((2, minor)) if minor < 13 => true
- case _ => false
- }
-
-lazy val sharedPublishSettings = Seq(
- releaseTagName := tagName.value,
- releaseVcsSign := true,
- publishMavenStyle := true,
- Test / publishArtifact := false,
- pomIncludeRepository := Function.const(false),
- publishTo := {
- val nexus = "https://oss.sonatype.org/"
- if (isSnapshot.value)
- Some("Snapshots".at(nexus + "content/repositories/snapshots"))
- else
- Some("Releases".at(nexus + "service/local/staging/deploy/maven2"))
- }
-)
-
-lazy val sharedReleaseProcess = Seq(
- releaseProcess := Seq[ReleaseStep](
- checkSnapshotDependencies,
- inquireVersions,
- runClean,
- runTest, // temporarily only run test in current scala version because docs won't build in 2.13 yet
- setReleaseVersion,
- commitReleaseVersion,
- tagRelease,
- releaseStepCommandAndRemaining("+publishSigned"),
- setNextVersion,
- commitNextVersion,
- releaseStepCommand("sonatypeReleaseAll"),
- pushChanges
+lazy val docs = project
+ .in(file("site"))
+ .enablePlugins(TypelevelSitePlugin)
+ .settings(
+ tlFatalWarnings := false,
+ mdocVariables += ("API_LINK_BASE" -> s"https://www.javadoc.io/doc/org.typelevel/cats-docs_2.13/${mdocVariables
+ .value("VERSION")}/"),
+ laikaConfig := {
+ import laika.config._
+
+ laikaConfig.value.withRawContent
+ .withConfigValue("version", mdocVariables.value("VERSION"))
+ .withConfigValue(
+ LinkConfig.empty
+ .addApiLinks(
+ ApiLinks(s"https://www.javadoc.io/doc/org.typelevel/cats-docs_2.13/${mdocVariables.value("VERSION")}/"),
+ ApiLinks(s"https://www.scala-lang.org/api/$Scala213/").withPackagePrefix("scala")
+ )
+ )
+ },
+ libraryDependencies ++= Seq(
+ "org.typelevel" %%% "discipline-munit" % disciplineMunitVersion
+ )
)
-)
+ .dependsOn(core.jvm, free.jvm, laws.jvm)
-lazy val warnUnusedImport = Seq(
- scalacOptions ++= (if (isDotty.value) Nil else Seq("-Ywarn-unused:imports")),
- Compile / console / scalacOptions ~= (_.filterNot(Set("-Ywarn-unused-import", "-Ywarn-unused:imports"))),
- Test / console / scalacOptions := (Compile / console / scalacOptions).value
+ThisBuild / licenses := List(License.MIT)
+ThisBuild / startYear := Some(2015)
+ThisBuild / developers ++= List(
+ tlGitHubDev("ceedubs", "Cody Allen"),
+ tlGitHubDev("rossabaker", "Ross Baker"),
+ tlGitHubDev("armanbilge", "Arman Bilge"),
+ tlGitHubDev("johnynek", "P. Oscar Boykin"),
+ tlGitHubDev("travisbrown", "Travis Brown"),
+ tlGitHubDev("adelbertc", "Adelbert Chang"),
+ tlGitHubDev("danicheg", "Daniel Esik"),
+ tlGitHubDev("peterneyens", "Peter Neyens"),
+ tlGitHubDev("tpolecat", "Rob Norris"),
+ tlGitHubDev("non", "Erik Osheim"),
+ tlGitHubDev("LukaJCB", "LukaJCB"),
+ tlGitHubDev("mpilquist", "Michael Pilquist"),
+ tlGitHubDev("milessabin", "Miles Sabin"),
+ tlGitHubDev("djspiewak", "Daniel Spiewak"),
+ tlGitHubDev("fthomas", "Frank Thomas"),
+ tlGitHubDev("satorg", "Sergey Torgashov"),
+ tlGitHubDev("julien-truffaut", "Julien Truffaut"),
+ tlGitHubDev("kailuowang", "Kailuo Wang")
)
diff --git a/core/src/main/scala-2.12/cats/ScalaVersionSpecificInstances.scala b/core/src/main/scala-2.12/cats/ScalaVersionSpecificInstances.scala
index c4b94161ab..2a8f359f45 100644
--- a/core/src/main/scala-2.12/cats/ScalaVersionSpecificInstances.scala
+++ b/core/src/main/scala-2.12/cats/ScalaVersionSpecificInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.data.ZipStream
diff --git a/core/src/main/scala-2.12/cats/compat/ChainCompat.scala b/core/src/main/scala-2.12/cats/compat/ChainCompat.scala
new file mode 100644
index 0000000000..b4c29c7cfb
--- /dev/null
+++ b/core/src/main/scala-2.12/cats/compat/ChainCompat.scala
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.data
+
+private[data] trait ChainCompat[+A] { _: Chain[A] =>
+
+ /**
+ * The number of elements in this chain, if it can be cheaply computed, -1 otherwise.
+ * Cheaply usually means: Not requiring a collection traversal.
+ */
+ final def knownSize: Long =
+ this match {
+ case Chain.Empty => 0
+ case Chain.Singleton(_) => 1
+ case _ => -1
+ }
+}
diff --git a/core/src/main/scala-2.12/cats/compat/FoldableCompat.scala b/core/src/main/scala-2.12/cats/compat/FoldableCompat.scala
index 88d162bd02..ea6631d723 100644
--- a/core/src/main/scala-2.12/cats/compat/FoldableCompat.scala
+++ b/core/src/main/scala-2.12/cats/compat/FoldableCompat.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package compat
diff --git a/core/src/main/scala-2.12/cats/compat/Seq.scala b/core/src/main/scala-2.12/cats/compat/Seq.scala
index fd6d03687d..ac140721fb 100644
--- a/core/src/main/scala-2.12/cats/compat/Seq.scala
+++ b/core/src/main/scala-2.12/cats/compat/Seq.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.compat
import scala.collection.immutable.{Seq => ISeq}
diff --git a/core/src/main/scala-2.12/cats/compat/SortedSet.scala b/core/src/main/scala-2.12/cats/compat/SortedSet.scala
index 6bfe60fd50..699bd022af 100644
--- a/core/src/main/scala-2.12/cats/compat/SortedSet.scala
+++ b/core/src/main/scala-2.12/cats/compat/SortedSet.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package compat
diff --git a/core/src/main/scala-2.12/cats/compat/Vector.scala b/core/src/main/scala-2.12/cats/compat/Vector.scala
index 31917aa3bf..99dc2b9947 100644
--- a/core/src/main/scala-2.12/cats/compat/Vector.scala
+++ b/core/src/main/scala-2.12/cats/compat/Vector.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.compat
private[cats] object Vector {
diff --git a/core/src/main/scala-2.12/cats/data/ChainCompanionCompat.scala b/core/src/main/scala-2.12/cats/data/ChainCompanionCompat.scala
new file mode 100644
index 0000000000..de7cd35d22
--- /dev/null
+++ b/core/src/main/scala-2.12/cats/data/ChainCompanionCompat.scala
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.data
+
+import cats.data.Chain.{nil, one, Wrap}
+import cats.kernel.compat.scalaVersionSpecific.IterableOnce
+
+import scala.collection.immutable
+
+private[data] trait ChainCompanionCompat {
+
+ /**
+ * Creates a Chain from the specified sequence.
+ */
+ def fromSeq[A](s: Seq[A]): Chain[A] =
+ s match {
+ case imm: immutable.Seq[A] => fromImmutableSeq(imm)
+ case _ => fromMutableSeq(s)
+ }
+
+ private def fromImmutableSeq[A](s: immutable.Seq[A]): Chain[A] = {
+ val lc = s.lengthCompare(1)
+ if (lc < 0) nil
+ else if (lc > 0) Wrap(s)
+ else one(s.head)
+ }
+
+ private def fromMutableSeq[A](s: Seq[A]): Chain[A] = {
+ val lc = s.lengthCompare(1)
+ if (lc < 0) nil
+ else if (lc > 0) Wrap(s.toVector)
+ else one(s.head)
+ }
+
+ /**
+ * Creates a Chain from the specified IterableOnce.
+ */
+ def fromIterableOnce[A](xs: IterableOnce[A]): Chain[A] =
+ xs match {
+ case s: immutable.Seq[A] => fromImmutableSeq(s) // pay O(1) not O(N) cost
+ case s: Seq[A] => fromMutableSeq(s)
+ case notSeq =>
+ fromImmutableSeq(notSeq.toVector) // toSeq could return a Stream, creating potential race conditions
+ }
+}
diff --git a/core/src/main/scala-2.12/cats/data/OneAndLowPriority4.scala b/core/src/main/scala-2.12/cats/data/OneAndLowPriority4.scala
index 4c5f6613d0..9ff6d9455d 100644
--- a/core/src/main/scala-2.12/cats/data/OneAndLowPriority4.scala
+++ b/core/src/main/scala-2.12/cats/data/OneAndLowPriority4.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala-2.12/cats/data/ScalaVersionSpecificNonEmptyChainImpl.scala b/core/src/main/scala-2.12/cats/data/ScalaVersionSpecificNonEmptyChainImpl.scala
index 35ca7ff5cf..8fa21d7a16 100644
--- a/core/src/main/scala-2.12/cats/data/ScalaVersionSpecificNonEmptyChainImpl.scala
+++ b/core/src/main/scala-2.12/cats/data/ScalaVersionSpecificNonEmptyChainImpl.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.data
private[data] trait ScalaVersionSpecificNonEmptyChainImpl {
diff --git a/core/src/main/scala-2.12/cats/data/ScalaVersionSpecificPackage.scala b/core/src/main/scala-2.12/cats/data/ScalaVersionSpecificPackage.scala
index b088ade790..258af6d53b 100644
--- a/core/src/main/scala-2.12/cats/data/ScalaVersionSpecificPackage.scala
+++ b/core/src/main/scala-2.12/cats/data/ScalaVersionSpecificPackage.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala-2.12/cats/data/ZipStream.scala b/core/src/main/scala-2.12/cats/data/ZipStream.scala
index 0e9a59ea07..b627e02f62 100644
--- a/core/src/main/scala-2.12/cats/data/ZipStream.scala
+++ b/core/src/main/scala-2.12/cats/data/ZipStream.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala-2.12/cats/evidence/AsSupport.scala b/core/src/main/scala-2.12/cats/evidence/AsSupport.scala
index cfc719d4e6..6e3862f646 100644
--- a/core/src/main/scala-2.12/cats/evidence/AsSupport.scala
+++ b/core/src/main/scala-2.12/cats/evidence/AsSupport.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.evidence
private[evidence] trait AsSupport {
diff --git a/core/src/main/scala-2.12/cats/evidence/IsSupport.scala b/core/src/main/scala-2.12/cats/evidence/IsSupport.scala
index caecd859bb..573a9f85c3 100644
--- a/core/src/main/scala-2.12/cats/evidence/IsSupport.scala
+++ b/core/src/main/scala-2.12/cats/evidence/IsSupport.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.evidence
private[evidence] trait IsSupport {
diff --git a/core/src/main/scala-2.12/cats/instances/ScalaVersionSpecificNumeric.scala b/core/src/main/scala-2.12/cats/instances/ScalaVersionSpecificNumeric.scala
index d6c178bfd8..854758896c 100644
--- a/core/src/main/scala-2.12/cats/instances/ScalaVersionSpecificNumeric.scala
+++ b/core/src/main/scala-2.12/cats/instances/ScalaVersionSpecificNumeric.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.instances
abstract private[instances] class ScalaVersionSpecificNumeric[A, B](fa: Numeric[A])(f: A => B)(g: B => A)
diff --git a/core/src/main/scala-2.12/cats/instances/ScalaVersionSpecificParallelInstances.scala b/core/src/main/scala-2.12/cats/instances/ScalaVersionSpecificParallelInstances.scala
index 211c39f614..c99ca4215d 100644
--- a/core/src/main/scala-2.12/cats/instances/ScalaVersionSpecificParallelInstances.scala
+++ b/core/src/main/scala-2.12/cats/instances/ScalaVersionSpecificParallelInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala-2.12/cats/instances/all.scala b/core/src/main/scala-2.12/cats/instances/all.scala
index 5e06ed7177..1628094e95 100644
--- a/core/src/main/scala-2.12/cats/instances/all.scala
+++ b/core/src/main/scala-2.12/cats/instances/all.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
@@ -35,6 +56,7 @@ trait AllInstances
with PartialOrderingInstances
with QueueInstances
with SetInstances
+ with ShowInstances
with SortedMapInstances
with SortedSetInstances
with StreamInstances
diff --git a/core/src/main/scala-2.12/cats/instances/package.scala b/core/src/main/scala-2.12/cats/instances/package.scala
index a5906db156..1c54805005 100644
--- a/core/src/main/scala-2.12/cats/instances/package.scala
+++ b/core/src/main/scala-2.12/cats/instances/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package object instances {
@@ -18,7 +39,18 @@ package object instances {
object deadline extends DeadlineInstances
object function extends FunctionInstances with FunctionInstancesBinCompat0
object partialFunction extends PartialFunctionInstances
+
+ /**
+ * @deprecated
+ * Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
+ * (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
+ * We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
+ * However, at this time there are no plans to remove these instances from Cats.
+ *
+ * @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
+ */
object future extends FutureInstances
+
object int extends IntInstances
object invariant extends InvariantMonoidalInstances with InvariantInstances with InvariantInstancesBinCompat0
object list extends ListInstances with ListInstancesBinCompat0
@@ -34,6 +66,7 @@ package object instances {
object set extends SetInstances
object seq extends SeqInstances
object short extends ShortInstances
+ object show extends ShowInstances
object sortedMap
extends SortedMapInstances
with SortedMapInstancesBinCompat0
diff --git a/core/src/main/scala-2.12/cats/instances/stream.scala b/core/src/main/scala-2.12/cats/instances/stream.scala
index 460557acf9..1bac2b9f42 100644
--- a/core/src/main/scala-2.12/cats/instances/stream.scala
+++ b/core/src/main/scala-2.12/cats/instances/stream.scala
@@ -1,11 +1,34 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import cats.data.{Ior, ZipStream}
+import cats.kernel.compat.scalaVersionSpecific._
import cats.syntax.show._
import scala.annotation.tailrec
+@suppressUnusedImportWarningForScalaVersionSpecific
trait StreamInstances extends cats.kernel.instances.StreamInstances {
implicit val catsStdInstancesForStream
@@ -16,6 +39,8 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances {
def combineK[A](x: Stream[A], y: Stream[A]): Stream[A] = x #::: y
+ override def fromIterableOnce[A](as: IterableOnce[A]): Stream[A] = as.iterator.toStream
+
override def prependK[A](a: A, fa: Stream[A]): Stream[A] = a #:: fa
def pure[A](x: A): Stream[A] = Stream(x)
@@ -169,9 +194,7 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances {
}
implicit def catsStdShowForStream[A: Show]: Show[Stream[A]] =
- new Show[Stream[A]] {
- def show(fa: Stream[A]): String = if (fa.isEmpty) "Stream()" else s"Stream(${fa.head.show}, ?)"
- }
+ stream => if (stream.isEmpty) "Stream()" else s"Stream(${stream.head.show}, ?)"
implicit def catsStdParallelForStreamZipStream: Parallel.Aux[Stream, ZipStream] =
new Parallel[Stream] {
diff --git a/core/src/main/scala-2.13+/cats/ScalaVersionSpecificInstances.scala b/core/src/main/scala-2.13+/cats/ScalaVersionSpecificInstances.scala
index ee443562a5..ca72612675 100644
--- a/core/src/main/scala-2.13+/cats/ScalaVersionSpecificInstances.scala
+++ b/core/src/main/scala-2.13+/cats/ScalaVersionSpecificInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.data.{ZipLazyList, ZipStream}
@@ -46,13 +67,13 @@ private[cats] trait ScalaVersionSpecificParallelInstances {
private[cats] trait ScalaVersionSpecificInvariantInstances {
@deprecated("Use catsInstancesForLazyList", "3.0.0")
- implicit def catsInstancesForStream: Monad[Stream] with Alternative[Stream] with CoflatMap[Stream] =
+ implicit def catsInstancesForStream: Monad[Stream] & Alternative[Stream] & CoflatMap[Stream] =
cats.instances.stream.catsStdInstancesForStream
- implicit def catsInstancesForLazyList: Monad[LazyList] with Alternative[LazyList] with CoflatMap[LazyList] =
+ implicit def catsInstancesForLazyList: Monad[LazyList] & Alternative[LazyList] & CoflatMap[LazyList] =
cats.instances.lazyList.catsStdInstancesForLazyList
- implicit def catsInstancesForArraySeq: Monad[ArraySeq] with Alternative[ArraySeq] with CoflatMap[ArraySeq] =
+ implicit def catsInstancesForArraySeq: Monad[ArraySeq] & Alternative[ArraySeq] & CoflatMap[ArraySeq] =
cats.instances.arraySeq.catsStdInstancesForArraySeq
}
diff --git a/core/src/main/scala-2.13+/cats/compat/FoldableCompat.scala b/core/src/main/scala-2.13+/cats/compat/FoldableCompat.scala
index 29bf40e7c4..622bd9a9c2 100644
--- a/core/src/main/scala-2.13+/cats/compat/FoldableCompat.scala
+++ b/core/src/main/scala-2.13+/cats/compat/FoldableCompat.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package compat
diff --git a/core/src/main/scala-2.13+/cats/compat/Seq.scala b/core/src/main/scala-2.13+/cats/compat/Seq.scala
index c5b158036c..93a3580dd3 100644
--- a/core/src/main/scala-2.13+/cats/compat/Seq.scala
+++ b/core/src/main/scala-2.13+/cats/compat/Seq.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.compat
import scala.collection.immutable.{Seq => ISeq}
diff --git a/core/src/main/scala-2.13+/cats/compat/SortedSet.scala b/core/src/main/scala-2.13+/cats/compat/SortedSet.scala
index 88d60e5561..c82b7992db 100644
--- a/core/src/main/scala-2.13+/cats/compat/SortedSet.scala
+++ b/core/src/main/scala-2.13+/cats/compat/SortedSet.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package compat
diff --git a/core/src/main/scala-2.13+/cats/compat/Vector.scala b/core/src/main/scala-2.13+/cats/compat/Vector.scala
index e3f0f5e223..beef2abf6f 100644
--- a/core/src/main/scala-2.13+/cats/compat/Vector.scala
+++ b/core/src/main/scala-2.13+/cats/compat/Vector.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.compat
private[cats] object Vector {
diff --git a/core/src/main/scala-2.13+/cats/data/ChainCompanionCompat.scala b/core/src/main/scala-2.13+/cats/data/ChainCompanionCompat.scala
new file mode 100644
index 0000000000..3821a1ce8c
--- /dev/null
+++ b/core/src/main/scala-2.13+/cats/data/ChainCompanionCompat.scala
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.data
+
+import cats.data.Chain.{nil, one, Wrap}
+
+private[data] trait ChainCompanionCompat {
+
+ /**
+ * Creates a Chain from the specified sequence.
+ */
+ def fromSeq[A](s: Seq[A]): Chain[A] = {
+ val lc = s.lengthCompare(1)
+ if (lc < 0) nil
+ else if (lc > 0) Wrap(s)
+ else one(s.head)
+ }
+
+ /**
+ * Creates a Chain from the specified IterableOnce.
+ */
+ def fromIterableOnce[A](xs: IterableOnce[A]): Chain[A] = Chain.fromSeq(
+ xs match {
+ case s: Seq[A] => s // pay O(1) not O(N) cost
+ case notSeq => notSeq.iterator.to(Vector) // toSeq could return a LazyList, creating potential race conditions
+ }
+ )
+}
diff --git a/core/src/main/scala-2.13+/cats/data/ChainCompat.scala b/core/src/main/scala-2.13+/cats/data/ChainCompat.scala
new file mode 100644
index 0000000000..8541f1356e
--- /dev/null
+++ b/core/src/main/scala-2.13+/cats/data/ChainCompat.scala
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats
+package data
+
+private[data] trait ChainCompat[+A] { self: Chain[A] =>
+
+ /**
+ * The number of elements in this chain, if it can be cheaply computed, -1 otherwise.
+ * Cheaply usually means: Not requiring a collection traversal.
+ */
+ final def knownSize: Long =
+ this match {
+ case Chain.Empty => 0
+ case Chain.Singleton(_) => 1
+ case Chain.Wrap(seq) => seq.knownSize.toLong
+ case _ => -1
+ }
+}
diff --git a/core/src/main/scala-2.13+/cats/data/NonEmptyLazyList.scala b/core/src/main/scala-2.13+/cats/data/NonEmptyLazyList.scala
index e9ac67ac7c..9e0547ef29 100644
--- a/core/src/main/scala-2.13+/cats/data/NonEmptyLazyList.scala
+++ b/core/src/main/scala-2.13+/cats/data/NonEmptyLazyList.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -17,7 +38,7 @@ object NonEmptyLazyList extends NonEmptyLazyListInstances {
private[data] type Base
private[data] trait Tag extends Any
/* aliased in data package as NonEmptyLazyList */
- type Type[+A] <: Base with Tag
+ type Type[+A] <: Base & Tag
private[data] def create[A](s: LazyList[A]): Type[A] =
s.asInstanceOf[Type[A]]
@@ -192,7 +213,7 @@ class NonEmptyLazyListOps[A](private val value: NonEmptyLazyList[A])
* Tests if some element is contained in this NonEmptyLazyList
*/
final def contains(a: A)(implicit A: Eq[A]): Boolean =
- toLazyList.contains(a)
+ toLazyList.exists(A.eqv(_, a))
/**
* Tests whether a predicate holds for all elements
@@ -324,14 +345,17 @@ class NonEmptyLazyListOps[A](private val value: NonEmptyLazyList[A])
/**
* Remove duplicates. Duplicates are checked using `Order[_]` instance.
*/
- def distinct[AA >: A](implicit O: Order[AA]): NonEmptyLazyList[AA] = {
- implicit val ord: Ordering[AA] = O.toOrdering
+ override def distinct[AA >: A](implicit O: Order[AA]): NonEmptyLazyList[AA] = distinctBy(identity[AA])
+
+ override def distinctBy[B](f: A => B)(implicit O: Order[B]): NonEmptyLazyList[A] = {
+ implicit val ord: Ordering[B] = O.toOrdering
- val buf = LazyList.newBuilder[AA]
- toLazyList.foldLeft(TreeSet.empty[AA]) { (elementsSoFar, a) =>
- if (elementsSoFar(a)) elementsSoFar
+ val buf = LazyList.newBuilder[A]
+ toLazyList.foldLeft(TreeSet.empty[B]) { (elementsSoFar, a) =>
+ val b = f(a)
+ if (elementsSoFar(b)) elementsSoFar
else {
- buf += a; elementsSoFar + a
+ buf += a; elementsSoFar + b
}
}
@@ -374,7 +398,7 @@ class NonEmptyLazyListOps[A](private val value: NonEmptyLazyList[A])
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.NonEmptyLazyList
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyLazyList(12, -2, 3, -5)
* scala> val expectedResult = SortedMap(false -> NonEmptyLazyList(-2, -5), true -> NonEmptyLazyList(12, 3))
* scala> val result = nel.groupBy(_ >= 0)
@@ -406,7 +430,7 @@ class NonEmptyLazyListOps[A](private val value: NonEmptyLazyList[A])
*
* {{{
* scala> import cats.data.{NonEmptyLazyList, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyLazyList(12, -2, 3, -5)
* scala> val expectedResult = NonEmptyMap.of(false -> NonEmptyLazyList(-2, -5), true -> NonEmptyLazyList(12, 3))
* scala> val result = nel.groupByNem(_ >= 0)
@@ -422,7 +446,7 @@ class NonEmptyLazyListOps[A](private val value: NonEmptyLazyList[A])
*
* {{{
* scala> import cats.data.NonEmptyLazyList
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyLazyList.fromLazyListUnsafe(LazyList(12, -2, 3, -5))
* scala> val expectedResult = List(
* | NonEmptyLazyList.fromLazyListUnsafe(LazyList(12, -2)),
@@ -442,7 +466,7 @@ class NonEmptyLazyListOps[A](private val value: NonEmptyLazyList[A])
* Creates new `NonEmptyMap`, similarly to List#toMap from scala standard library.
* {{{
* scala> import cats.data.{NonEmptyLazyList, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyLazyList.fromLazyListPrepend((0, "a"), LazyList((1, "b"),(0, "c"), (2, "d")))
* scala> val expectedResult = NonEmptyMap.of(0 -> "c", 1 -> "b", 2 -> "d")
* scala> val result = nel.toNem
@@ -486,10 +510,9 @@ class NonEmptyLazyListOps[A](private val value: NonEmptyLazyList[A])
sealed abstract private[data] class NonEmptyLazyListInstances extends NonEmptyLazyListInstances1 {
- implicit val catsDataInstancesForNonEmptyLazyList: Bimonad[NonEmptyLazyList]
- with NonEmptyTraverse[NonEmptyLazyList]
- with SemigroupK[NonEmptyLazyList]
- with Align[NonEmptyLazyList] =
+ implicit val catsDataInstancesForNonEmptyLazyList: Bimonad[NonEmptyLazyList] & NonEmptyTraverse[
+ NonEmptyLazyList
+ ] & NonEmptyAlternative[NonEmptyLazyList] & Align[NonEmptyLazyList] =
new AbstractNonEmptyInstances[LazyList, NonEmptyLazyList] with Align[NonEmptyLazyList] {
def extract[A](fa: NonEmptyLazyList[A]): A = fa.head
@@ -532,8 +555,7 @@ sealed abstract private[data] class NonEmptyLazyListInstances extends NonEmptyLa
implicit def catsDataSemigroupForNonEmptyLazyList[A]: Semigroup[NonEmptyLazyList[A]] =
Semigroup[LazyList[A]].asInstanceOf[Semigroup[NonEmptyLazyList[A]]]
- implicit def catsDataShowForNonEmptyLazyList[A](implicit A: Show[A]): Show[NonEmptyLazyList[A]] =
- Show.show[NonEmptyLazyList[A]](_.show)
+ implicit def catsDataShowForNonEmptyLazyList[A: Show]: Show[NonEmptyLazyList[A]] = _.show
implicit def catsDataParallelForNonEmptyLazyList: Parallel.Aux[NonEmptyLazyList, OneAnd[ZipLazyList, *]] =
new Parallel[NonEmptyLazyList] {
diff --git a/core/src/main/scala-2.13+/cats/data/OneAndLowPriority4.scala b/core/src/main/scala-2.13+/cats/data/OneAndLowPriority4.scala
index 3f08c7bdd8..bc61e2526a 100644
--- a/core/src/main/scala-2.13+/cats/data/OneAndLowPriority4.scala
+++ b/core/src/main/scala-2.13+/cats/data/OneAndLowPriority4.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala-2.13+/cats/data/ScalaVersionSpecificNonEmptyChainImpl.scala b/core/src/main/scala-2.13+/cats/data/ScalaVersionSpecificNonEmptyChainImpl.scala
index 5005b53f9c..6fe104df42 100644
--- a/core/src/main/scala-2.13+/cats/data/ScalaVersionSpecificNonEmptyChainImpl.scala
+++ b/core/src/main/scala-2.13+/cats/data/ScalaVersionSpecificNonEmptyChainImpl.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.data
private[data] trait ScalaVersionSpecificNonEmptyChainImpl
diff --git a/core/src/main/scala-2.13+/cats/data/ScalaVersionSpecificPackage.scala b/core/src/main/scala-2.13+/cats/data/ScalaVersionSpecificPackage.scala
index 6f4c639df8..61f54202e9 100644
--- a/core/src/main/scala-2.13+/cats/data/ScalaVersionSpecificPackage.scala
+++ b/core/src/main/scala-2.13+/cats/data/ScalaVersionSpecificPackage.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala-2.13+/cats/data/ZipLazyList.scala b/core/src/main/scala-2.13+/cats/data/ZipLazyList.scala
index 20c4832560..0f5d552636 100644
--- a/core/src/main/scala-2.13+/cats/data/ZipLazyList.scala
+++ b/core/src/main/scala-2.13+/cats/data/ZipLazyList.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -7,7 +28,7 @@ object ZipLazyList {
def apply[A](value: LazyList[A]): ZipLazyList[A] = new ZipLazyList(value)
- implicit val catsDataAlternativeForZipLazyList: Alternative[ZipLazyList] with CommutativeApplicative[ZipLazyList] =
+ implicit val catsDataAlternativeForZipLazyList: Alternative[ZipLazyList] & CommutativeApplicative[ZipLazyList] =
new Alternative[ZipLazyList] with CommutativeApplicative[ZipLazyList] {
def pure[A](x: A): ZipLazyList[A] = new ZipLazyList(LazyList.continually(x))
diff --git a/core/src/main/scala-2.13+/cats/data/ZipStream.scala b/core/src/main/scala-2.13+/cats/data/ZipStream.scala
index fbb375eca8..1f80ceef78 100644
--- a/core/src/main/scala-2.13+/cats/data/ZipStream.scala
+++ b/core/src/main/scala-2.13+/cats/data/ZipStream.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -9,7 +30,7 @@ object ZipStream {
def apply[A](value: Stream[A]): ZipStream[A] = new ZipStream(value)
- implicit val catsDataAlternativeForZipStream: Alternative[ZipStream] with CommutativeApplicative[ZipStream] =
+ implicit val catsDataAlternativeForZipStream: Alternative[ZipStream] & CommutativeApplicative[ZipStream] =
new Alternative[ZipStream] with CommutativeApplicative[ZipStream] {
def pure[A](x: A): ZipStream[A] = new ZipStream(Stream.continually(x))
diff --git a/core/src/main/scala-2.13+/cats/evidence/AsSupport.scala b/core/src/main/scala-2.13+/cats/evidence/AsSupport.scala
index 53fd40df16..c2f9064814 100644
--- a/core/src/main/scala-2.13+/cats/evidence/AsSupport.scala
+++ b/core/src/main/scala-2.13+/cats/evidence/AsSupport.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.evidence
private[evidence] trait AsSupport {
diff --git a/core/src/main/scala-2.13+/cats/evidence/IsSupport.scala b/core/src/main/scala-2.13+/cats/evidence/IsSupport.scala
index a4d1ce74fc..156a9363ec 100644
--- a/core/src/main/scala-2.13+/cats/evidence/IsSupport.scala
+++ b/core/src/main/scala-2.13+/cats/evidence/IsSupport.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.evidence
private[evidence] trait IsSupport {
diff --git a/core/src/main/scala-2.13+/cats/instances/ScalaVersionSpecificNumeric.scala b/core/src/main/scala-2.13+/cats/instances/ScalaVersionSpecificNumeric.scala
index 13b1426508..1b507f7384 100644
--- a/core/src/main/scala-2.13+/cats/instances/ScalaVersionSpecificNumeric.scala
+++ b/core/src/main/scala-2.13+/cats/instances/ScalaVersionSpecificNumeric.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.instances
abstract private[instances] class ScalaVersionSpecificNumeric[A, B](fa: Numeric[A])(f: A => B)(g: B => A)
diff --git a/core/src/main/scala-2.13+/cats/instances/ScalaVersionSpecificParallelInstances.scala b/core/src/main/scala-2.13+/cats/instances/ScalaVersionSpecificParallelInstances.scala
index c3ee090617..aeef20c27e 100644
--- a/core/src/main/scala-2.13+/cats/instances/ScalaVersionSpecificParallelInstances.scala
+++ b/core/src/main/scala-2.13+/cats/instances/ScalaVersionSpecificParallelInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala-2.13+/cats/instances/all.scala b/core/src/main/scala-2.13+/cats/instances/all.scala
index 8ea017d83b..f57d80ac52 100644
--- a/core/src/main/scala-2.13+/cats/instances/all.scala
+++ b/core/src/main/scala-2.13+/cats/instances/all.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
@@ -40,6 +61,7 @@ trait AllInstances
with SetInstances
with SortedMapInstances
with SortedSetInstances
+ with ShowInstances
with StreamInstances
with StringInstances
with SymbolInstances
diff --git a/core/src/main/scala-2.13+/cats/instances/arraySeq.scala b/core/src/main/scala-2.13+/cats/instances/arraySeq.scala
index 0047ab7e98..33c34b25d3 100644
--- a/core/src/main/scala-2.13+/cats/instances/arraySeq.scala
+++ b/core/src/main/scala-2.13+/cats/instances/arraySeq.scala
@@ -1,28 +1,47 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
-import cats.data.Ior
+import cats.data.{Chain, Ior}
import scala.annotation.tailrec
import scala.collection.immutable.ArraySeq
import scala.collection.mutable.Builder
trait ArraySeqInstances extends cats.kernel.instances.ArraySeqInstances {
implicit def catsStdInstancesForArraySeq
- : Traverse[ArraySeq] with Monad[ArraySeq] with Alternative[ArraySeq] with CoflatMap[ArraySeq] with Align[ArraySeq] =
+ : Traverse[ArraySeq] & Monad[ArraySeq] & Alternative[ArraySeq] & CoflatMap[ArraySeq] & Align[ArraySeq] =
ArraySeqInstances.stdInstances
implicit def catsStdTraverseFilterForArraySeq: TraverseFilter[ArraySeq] =
ArraySeqInstances.stdTraverseFilterInstance
implicit def catsStdShowForArraySeq[A](implicit ev: Show[A]): Show[ArraySeq[A]] =
- Show.show { arraySeq =>
- arraySeq.iterator.map(ev.show).mkString("ArraySeq(", ", ", ")")
- }
+ _.iterator.map(ev.show).mkString("ArraySeq(", ", ", ")")
}
private[cats] object ArraySeqInstances {
final private val stdInstances
- : Traverse[ArraySeq] with Monad[ArraySeq] with Alternative[ArraySeq] with CoflatMap[ArraySeq] with Align[ArraySeq] =
+ : Traverse[ArraySeq] & Monad[ArraySeq] & Alternative[ArraySeq] & CoflatMap[ArraySeq] & Align[ArraySeq] =
new Traverse[ArraySeq]
with Monad[ArraySeq]
with Alternative[ArraySeq]
@@ -34,6 +53,8 @@ private[cats] object ArraySeqInstances {
def combineK[A](xs: ArraySeq[A], ys: ArraySeq[A]): ArraySeq[A] =
xs.concat(ys)
+ override def fromIterableOnce[A](as: IterableOnce[A]): ArraySeq[A] = ArraySeq.untagged.from(as)
+
override def prependK[A](a: A, fa: ArraySeq[A]): ArraySeq[A] = fa.prepended(a)
override def appendK[A](fa: ArraySeq[A], a: A): ArraySeq[A] = fa.appended(a)
@@ -80,12 +101,28 @@ private[cats] object ArraySeqInstances {
override def foldMap[A, B](fa: ArraySeq[A])(f: A => B)(implicit B: Monoid[B]): B =
B.combineAll(fa.iterator.map(f))
- def traverse[G[_], A, B](fa: ArraySeq[A])(f: A => G[B])(implicit G: Applicative[G]): G[ArraySeq[B]] = {
- def loop(i: Int): Eval[G[ArraySeq[B]]] =
- if (i < fa.length) G.map2Eval(f(fa(i)), Eval.defer(loop(i + 1)))(_ +: _)
- else Eval.now(G.pure(ArraySeq.untagged.empty))
- loop(0).value
- }
+ def traverse[G[_], A, B](fa: ArraySeq[A])(f: A => G[B])(implicit G: Applicative[G]): G[ArraySeq[B]] =
+ G match {
+ case x: StackSafeMonad[G] =>
+ x.map(Traverse.traverseDirectly(fa.iterator)(f)(x))(_.iterator.to(ArraySeq.untagged))
+ case _ =>
+ G.map(Chain.traverseViaChain(fa)(f))(_.iterator.to(ArraySeq.untagged))
+
+ }
+
+ override def traverseVoid[G[_], A, B](fa: ArraySeq[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] =
+ G match {
+ case x: StackSafeMonad[G] => Traverse.traverseVoidDirectly(fa)(f)(x)
+ case _ =>
+ foldRight(fa, Eval.now(G.unit)) { (a, acc) =>
+ G.map2Eval(f(a), acc) { (_, _) =>
+ ()
+ }
+ }.value
+ }
+
+ override def mapAccumulate[S, A, B](init: S, fa: ArraySeq[A])(f: (S, A) => (S, B)): (S, ArraySeq[B]) =
+ StaticMethods.mapAccumulateFromStrictFunctor(init, fa, f)(this)
override def mapWithIndex[A, B](fa: ArraySeq[A])(f: (A, Int) => B): ArraySeq[B] =
ArraySeq.untagged.tabulate(n = fa.length) { i =>
@@ -194,9 +231,17 @@ private[cats] object ArraySeqInstances {
def traverseFilter[G[_], A, B](
fa: ArraySeq[A]
)(f: (A) => G[Option[B]])(implicit G: Applicative[G]): G[ArraySeq[B]] =
- fa.foldRight(Eval.now(G.pure(ArraySeq.untagged.empty[B]))) { case (x, xse) =>
- G.map2Eval(f(x), xse)((i, o) => i.fold(o)(_ +: o))
- }.value
+ G match {
+ case x: StackSafeMonad[G] =>
+ x.map(TraverseFilter.traverseFilterDirectly(fa.iterator)(f)(x))(
+ _.iterator.to(ArraySeq.untagged)
+ )
+ case _ =>
+ fa.foldRight(Eval.now(G.pure(ArraySeq.untagged.empty[B]))) { case (x, xse) =>
+ G.map2Eval(f(x), xse)((i, o) => i.fold(o)(_ +: o))
+ }.value
+
+ }
override def filterA[G[_], A](fa: ArraySeq[A])(f: (A) => G[Boolean])(implicit G: Applicative[G]): G[ArraySeq[A]] =
fa.foldRight(Eval.now(G.pure(ArraySeq.untagged.empty[A]))) { case (x, xse) =>
diff --git a/core/src/main/scala-2.13+/cats/instances/lazyList.scala b/core/src/main/scala-2.13+/cats/instances/lazyList.scala
index 7b2796444b..3140de76e1 100644
--- a/core/src/main/scala-2.13+/cats/instances/lazyList.scala
+++ b/core/src/main/scala-2.13+/cats/instances/lazyList.scala
@@ -1,17 +1,40 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import cats.kernel
+import cats.kernel.compat.scalaVersionSpecific._
import cats.syntax.show._
import cats.data.Ior
import cats.data.ZipLazyList
import scala.annotation.tailrec
+@suppressUnusedImportWarningForScalaVersionSpecific
trait LazyListInstances extends cats.kernel.instances.LazyListInstances {
implicit val catsStdInstancesForLazyList
- : Traverse[LazyList] with Alternative[LazyList] with Monad[LazyList] with CoflatMap[LazyList] with Align[LazyList] =
+ : Traverse[LazyList] & Alternative[LazyList] & Monad[LazyList] & CoflatMap[LazyList] & Align[LazyList] =
new Traverse[LazyList]
with Alternative[LazyList]
with Monad[LazyList]
@@ -22,6 +45,13 @@ trait LazyListInstances extends cats.kernel.instances.LazyListInstances {
def combineK[A](x: LazyList[A], y: LazyList[A]): LazyList[A] = x.lazyAppendedAll(y)
+ override def combineAllOptionK[A](as: IterableOnce[LazyList[A]]): Option[LazyList[A]] = {
+ val iter = as.iterator
+ if (iter.isEmpty) None else Some(LazyList.from(iter.flatMap(_.iterator)))
+ }
+
+ override def fromIterableOnce[A](as: IterableOnce[A]): LazyList[A] = LazyList.from(as)
+
override def prependK[A](a: A, fa: LazyList[A]): LazyList[A] = fa.prepended(a)
override def appendK[A](fa: LazyList[A], a: A): LazyList[A] = fa.appended(a)
@@ -129,7 +159,7 @@ trait LazyListInstances extends cats.kernel.instances.LazyListInstances {
override def find[A](fa: LazyList[A])(f: A => Boolean): Option[A] = fa.find(f)
- override def algebra[A]: Monoid[LazyList[A]] = new kernel.instances.LazyListMonoid[A]
+ override def algebra[A]: Monoid[LazyList[A]] = kernel.instances.LazyListMonoid[A]
override def collectFirst[A, B](fa: LazyList[A])(pf: PartialFunction[A, B]): Option[B] = fa.collectFirst(pf)
@@ -146,9 +176,7 @@ trait LazyListInstances extends cats.kernel.instances.LazyListInstances {
}
implicit def catsStdShowForLazyList[A: Show]: Show[LazyList[A]] =
- new Show[LazyList[A]] {
- def show(fa: LazyList[A]): String = if (fa.isEmpty) "LazyList()" else s"LazyList(${fa.head.show}, ?)"
- }
+ list => if (list.isEmpty) "LazyList()" else s"LazyList(${list.head.show}, ?)"
implicit val catsStdTraverseFilterForLazyList: TraverseFilter[LazyList] = new TraverseFilter[LazyList] {
val traverse: Traverse[LazyList] = catsStdInstancesForLazyList
diff --git a/core/src/main/scala-2.13+/cats/instances/package.scala b/core/src/main/scala-2.13+/cats/instances/package.scala
index 3f724ceee4..2ee72b37db 100644
--- a/core/src/main/scala-2.13+/cats/instances/package.scala
+++ b/core/src/main/scala-2.13+/cats/instances/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package object instances {
@@ -19,7 +40,18 @@ package object instances {
object deadline extends DeadlineInstances
object function extends FunctionInstances with FunctionInstancesBinCompat0
object partialFunction extends PartialFunctionInstances
+
+ /**
+ * @deprecated
+ * Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
+ * (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
+ * We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
+ * However, at this time there are no plans to remove these instances from Cats.
+ *
+ * @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
+ */
object future extends FutureInstances
+
object int extends IntInstances
object invariant extends InvariantMonoidalInstances with InvariantInstances with InvariantInstancesBinCompat0
object list extends ListInstances with ListInstancesBinCompat0
@@ -35,6 +67,7 @@ package object instances {
object set extends SetInstances
object seq extends SeqInstances
object short extends ShortInstances
+ object show extends ShowInstances
object sortedMap
extends SortedMapInstances
with SortedMapInstancesBinCompat0
diff --git a/core/src/main/scala-2.13+/cats/instances/stream.scala b/core/src/main/scala-2.13+/cats/instances/stream.scala
index f835f92462..c011caae7a 100644
--- a/core/src/main/scala-2.13+/cats/instances/stream.scala
+++ b/core/src/main/scala-2.13+/cats/instances/stream.scala
@@ -1,22 +1,47 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import cats.data.{Ior, ZipStream}
+import cats.kernel.compat.scalaVersionSpecific._
import cats.syntax.show._
import scala.annotation.tailrec
+@suppressUnusedImportWarningForScalaVersionSpecific
trait StreamInstances extends cats.kernel.instances.StreamInstances {
@deprecated("Use cats.instances.lazyList", "2.0.0-RC2")
implicit val catsStdInstancesForStream
- : Traverse[Stream] with Alternative[Stream] with Monad[Stream] with CoflatMap[Stream] with Align[Stream] =
+ : Traverse[Stream] & Alternative[Stream] & Monad[Stream] & CoflatMap[Stream] & Align[Stream] =
new Traverse[Stream] with Alternative[Stream] with Monad[Stream] with CoflatMap[Stream] with Align[Stream] {
def empty[A]: Stream[A] = Stream.Empty
def combineK[A](x: Stream[A], y: Stream[A]): Stream[A] = x #::: y
+ override def fromIterableOnce[A](as: IterableOnce[A]): Stream[A] = Stream.from(as)
+
override def prependK[A](a: A, fa: Stream[A]): Stream[A] = a #:: fa
def pure[A](x: A): Stream[A] = Stream(x)
@@ -79,7 +104,7 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances {
case Left(a) #:: tail =>
stack = fn(a) #::: tail
advance()
- case empty =>
+ case _ => // empty
state = Right(None)
}
@@ -171,9 +196,7 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances {
@deprecated("Use cats.instances.lazyList", "2.0.0-RC2")
implicit def catsStdShowForStream[A: Show]: Show[Stream[A]] =
- new Show[Stream[A]] {
- def show(fa: Stream[A]): String = if (fa.isEmpty) "Stream()" else s"Stream(${fa.head.show}, ?)"
- }
+ stream => if (stream.isEmpty) "Stream()" else s"Stream(${stream.head.show}, ?)"
@deprecated("Use catsStdParallelForZipLazyList", "2.0.0-RC2")
implicit def catsStdParallelForStreamZipStream: Parallel.Aux[Stream, ZipStream] =
diff --git a/core/src/main/scala-2.x/src/main/scala/cats/syntax/MonadOps.scala b/core/src/main/scala-2.x/src/main/scala/cats/syntax/MonadOps.scala
deleted file mode 100644
index 009aea662c..0000000000
--- a/core/src/main/scala-2.x/src/main/scala/cats/syntax/MonadOps.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package cats.syntax
-
-import cats.{Alternative, Monad}
-
-final class MonadOps[F[_], A](private val fa: F[A]) extends AnyVal {
- def whileM[G[_]](p: F[Boolean])(implicit M: Monad[F], G: Alternative[G]): F[G[A]] = M.whileM(p)(fa)
- def whileM_(p: F[Boolean])(implicit M: Monad[F]): F[Unit] = M.whileM_(p)(fa)
- def untilM[G[_]](p: F[Boolean])(implicit M: Monad[F], G: Alternative[G]): F[G[A]] = M.untilM(fa)(p)
- def untilM_(p: F[Boolean])(implicit M: Monad[F]): F[Unit] = M.untilM_(fa)(p)
- def iterateWhile(p: A => Boolean)(implicit M: Monad[F]): F[A] = M.iterateWhile(fa)(p)
- def iterateUntil(p: A => Boolean)(implicit M: Monad[F]): F[A] = M.iterateUntil(fa)(p)
-}
diff --git a/core/src/main/scala-2.x/src/main/scala/cats/arrow/FunctionKMacros.scala b/core/src/main/scala-2/cats/arrow/FunctionKMacros.scala
similarity index 65%
rename from core/src/main/scala-2.x/src/main/scala/cats/arrow/FunctionKMacros.scala
rename to core/src/main/scala-2/cats/arrow/FunctionKMacros.scala
index 6a9bbc7d45..08b02bec7f 100644
--- a/core/src/main/scala-2.x/src/main/scala/cats/arrow/FunctionKMacros.scala
+++ b/core/src/main/scala-2/cats/arrow/FunctionKMacros.scala
@@ -1,11 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package arrow
-import scala.language.experimental.macros
import scala.reflect.macros.blackbox
-private[arrow] class FunctionKMacroMethods {
- protected type τ[F[_], G[_]]
+private[arrow] class FunctionKMacroMethods extends FunctionKLift {
/**
* Lifts function `f` of `F[A] => G[A]` into a `FunctionK[F, G]`.
@@ -28,22 +47,6 @@ private[arrow] class FunctionKMacroMethods {
*/
def lift[F[_], G[_]](f: (F[α] => G[α]) forSome { type α }): FunctionK[F, G] =
macro FunctionKMacros.lift[F, G]
-
- /**
- * Lifts function `f` of `F[A] => G[A]` into a `FunctionK[F, G]`.
- *
- * {{{
- * def headOption[A](list: List[A]): Option[A] = list.headOption
- * val lifted = FunctionK.liftFunction[List, Option](headOption)
- * }}}
- *
- * Note: The weird `τ[F, G]` parameter is there to compensate for
- * the lack of polymorphic function types in Scala 2.
- */
- def liftFunction[F[_], G[_]](f: F[τ[F, G]] => G[τ[F, G]]): FunctionK[F, G] =
- new FunctionK[F, G] {
- def apply[A](fa: F[A]): G[A] = f.asInstanceOf[F[A] => G[A]](fa)
- }
}
private[arrow] object FunctionKMacros {
diff --git a/core/src/main/scala-2/cats/syntax/MonadOps.scala b/core/src/main/scala-2/cats/syntax/MonadOps.scala
new file mode 100644
index 0000000000..cc2b782378
--- /dev/null
+++ b/core/src/main/scala-2/cats/syntax/MonadOps.scala
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.syntax
+
+import cats.{Alternative, Monad}
+
+final class MonadOps[F[_], A](private val fa: F[A]) extends AnyVal {
+ def whileM[G[_]](p: F[Boolean])(implicit M: Monad[F], G: Alternative[G]): F[G[A]] = M.whileM(p)(fa)
+ def whileM_(p: F[Boolean])(implicit M: Monad[F]): F[Unit] = M.whileM_(p)(fa)
+ def untilM[G[_]](p: F[Boolean])(implicit M: Monad[F], G: Alternative[G]): F[G[A]] = M.untilM(fa)(p)
+ def untilM_(p: F[Boolean])(implicit M: Monad[F]): F[Unit] = M.untilM_(fa)(p)
+ def iterateWhile(p: A => Boolean)(implicit M: Monad[F]): F[A] = M.iterateWhile(fa)(p)
+ def iterateUntil(p: A => Boolean)(implicit M: Monad[F]): F[A] = M.iterateUntil(fa)(p)
+ def flatMapOrKeep[A1 >: A](pfa: PartialFunction[A, F[A1]])(implicit M: Monad[F]): F[A1] =
+ M.flatMapOrKeep[A, A1](fa)(pfa)
+}
diff --git a/core/src/main/scala-3.x/src/main/scala/cats/arrow/FunctionKMacros.scala b/core/src/main/scala-3.x/src/main/scala/cats/arrow/FunctionKMacros.scala
deleted file mode 100644
index 639b6ccf7f..0000000000
--- a/core/src/main/scala-3.x/src/main/scala/cats/arrow/FunctionKMacros.scala
+++ /dev/null
@@ -1,4 +0,0 @@
-package cats
-package arrow
-
-private[arrow] class FunctionKMacroMethods
diff --git a/core/src/main/scala-3.x/src/main/scala/cats/syntax/MonadOps.scala b/core/src/main/scala-3.x/src/main/scala/cats/syntax/MonadOps.scala
deleted file mode 100644
index 8f445403ea..0000000000
--- a/core/src/main/scala-3.x/src/main/scala/cats/syntax/MonadOps.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package cats.syntax
-
-import cats.{Alternative, Monad}
-
-final class MonadOps[F[_], A](private val fa: F[A]) extends AnyVal {
- def whileM[G[_]](using M: Monad[F], G: Alternative[G])(p: F[Boolean]): F[G[A]] = M.whileM(p)(fa)
- def whileM_(using M: Monad[F])(p: F[Boolean]): F[Unit] = M.whileM_(p)(fa)
- def untilM[G[_]](using M: Monad[F], G: Alternative[G])(p: F[Boolean]): F[G[A]] = M.untilM(fa)(p)
- def untilM_(using M: Monad[F])(p: F[Boolean]): F[Unit] = M.untilM_(fa)(p)
- def iterateWhile(using M: Monad[F])(p: A => Boolean): F[A] = M.iterateWhile(fa)(p)
- def iterateUntil(using M: Monad[F])(p: A => Boolean): F[A] = M.iterateUntil(fa)(p)
-}
diff --git a/core/src/main/scala-3/cats/arrow/FunctionKMacros.scala b/core/src/main/scala-3/cats/arrow/FunctionKMacros.scala
new file mode 100644
index 0000000000..76e7f22905
--- /dev/null
+++ b/core/src/main/scala-3/cats/arrow/FunctionKMacros.scala
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats
+package arrow
+
+private[arrow] class FunctionKMacroMethods extends FunctionKLift {
+
+ /**
+ * Lifts function `f` of `[X] => F[X] => G[X]` into a `FunctionK[F, G]`.
+ *
+ * {{{
+ * val headOptionK = FunctionK.lift[List, Option]([X] => (_: List[X]).headOption)
+ * }}}
+ */
+ def lift[F[_], G[_]](f: [X] => F[X] => G[X]): FunctionK[F, G] =
+ new FunctionK[F, G] {
+ def apply[A](fa: F[A]): G[A] = f(fa)
+ }
+
+}
diff --git a/core/src/main/scala-3/cats/syntax/MonadOps.scala b/core/src/main/scala-3/cats/syntax/MonadOps.scala
new file mode 100644
index 0000000000..7924b01b34
--- /dev/null
+++ b/core/src/main/scala-3/cats/syntax/MonadOps.scala
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.syntax
+
+import cats.{Alternative, Monad}
+
+final class MonadOps[F[_], A](private val fa: F[A]) extends AnyVal {
+ def whileM[G[_]](using M: Monad[F], G: Alternative[G])(p: F[Boolean]): F[G[A]] = M.whileM(p)(fa)
+ def whileM_(using M: Monad[F])(p: F[Boolean]): F[Unit] = M.whileM_(p)(fa)
+ def untilM[G[_]](using M: Monad[F], G: Alternative[G])(p: F[Boolean]): F[G[A]] = M.untilM(fa)(p)
+ def untilM_(using M: Monad[F])(p: F[Boolean]): F[Unit] = M.untilM_(fa)(p)
+ def iterateWhile(using M: Monad[F])(p: A => Boolean): F[A] = M.iterateWhile(fa)(p)
+ def iterateUntil(using M: Monad[F])(p: A => Boolean): F[A] = M.iterateUntil(fa)(p)
+ def flatMapOrKeep[A1 >: A](using M: Monad[F])(pfa: PartialFunction[A, F[A1]]): F[A1] =
+ M.flatMapOrKeep[A, A1](fa)(pfa)
+}
diff --git a/core/src/main/scala/cats/Align.scala b/core/src/main/scala/cats/Align.scala
index d943105e6f..0b871930cc 100644
--- a/core/src/main/scala/cats/Align.scala
+++ b/core/src/main/scala/cats/Align.scala
@@ -1,10 +1,28 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
+package cats
import cats.data.Ior
import scala.collection.immutable.{Seq, SortedMap}
-import scala.annotation.implicitNotFound
/**
* `Align` supports zipping together structures with different shapes,
@@ -12,8 +30,7 @@ import scala.annotation.implicitNotFound
*
* Must obey the laws in cats.laws.AlignLaws
*/
-@implicitNotFound("Could not find an instance of Align for ${F}")
-@typeclass trait Align[F[_]] extends Serializable {
+trait Align[F[_]] extends Serializable {
def functor: Functor[F]
@@ -22,7 +39,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.Ior
* scala> Align[List].align(List(1, 2), List(10, 11, 12))
* res0: List[Ior[Int, Int]] = List(Both(1,10), Both(2,11), Right(12))
@@ -35,7 +52,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> Align[List].alignWith(List(1, 2), List(10, 11, 12))(_.mergeLeft)
* res0: List[Int] = List(1, 2, 12)
* }}}
@@ -48,7 +65,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> Align[List].alignCombine(List(1, 2), List(10, 11, 12))
* res0: List[Int] = List(11, 13, 12)
* }}}
@@ -61,20 +78,20 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> Align[List].alignMergeWith(List(1, 2), List(10, 11, 12))(_ + _)
* res0: List[Int] = List(11, 13, 12)
* }}}
*/
def alignMergeWith[A](fa1: F[A], fa2: F[A])(f: (A, A) => A): F[A] =
- functor.map(align(fa1, fa2))(_.mergeWith(f))
+ alignWith(fa1, fa2)(_.mergeWith(f))
/**
* Same as `align`, but forgets from the type that one of the two elements must be present.
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> Align[List].padZip(List(1, 2), List(10))
* res0: List[(Option[Int], Option[Int])] = List((Some(1),Some(10)), (Some(2),None))
* }}}
@@ -87,7 +104,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> Align[List].padZipWith(List(1, 2), List(10, 11, 12))(_ |+| _)
* res0: List[Option[Int]] = List(Some(11), Some(13), Some(12))
* }}}
@@ -103,7 +120,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> Align[List].zipAll(List(1, 2), List(10, 11, 12), 20, 21)
* res0: List[(Int, Int)] = List((1,10), (2,11), (20,12))
* }}}
@@ -118,9 +135,7 @@ import scala.annotation.implicitNotFound
object Align extends ScalaVersionSpecificAlignInstances {
def semigroup[F[_], A](implicit F: Align[F], A: Semigroup[A]): Semigroup[F[A]] =
- new Semigroup[F[A]] {
- def combine(x: F[A], y: F[A]): F[A] = Align[F].alignCombine(x, y)
- }
+ F.alignCombine(_, _)
implicit def catsAlignForList: Align[List] = cats.instances.list.catsStdInstancesForList
implicit def catsAlignForOption: Align[Option] = cats.instances.option.catsStdInstancesForOption
@@ -130,6 +145,7 @@ object Align extends ScalaVersionSpecificAlignInstances {
implicit def catsAlignForSortedMap[K]: Align[SortedMap[K, *]] =
cats.instances.sortedMap.catsStdInstancesForSortedMap[K]
implicit def catsAlignForEither[A]: Align[Either[A, *]] = cats.instances.either.catsStdInstancesForEither[A]
+ implicit def catsAlignForId: Align[Id] = cats.catsAlignForId
private[cats] def alignWithIterator[A, B, C](fa: Iterable[A], fb: Iterable[B])(f: Ior[A, B] => C): Iterator[C] =
new Iterator[C] {
@@ -144,10 +160,6 @@ object Align extends ScalaVersionSpecificAlignInstances {
)
}
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Align]] for `F`.
*/
@@ -191,8 +203,4 @@ object Align extends ScalaVersionSpecificAlignInstances {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToAlignOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/Alternative.scala b/core/src/main/scala/cats/Alternative.scala
index 1f8643d091..e2cce09bcf 100644
--- a/core/src/main/scala/cats/Alternative.scala
+++ b/core/src/main/scala/cats/Alternative.scala
@@ -1,10 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+import cats.kernel.compat.scalaVersionSpecific._
-@implicitNotFound("Could not find an instance of Alternative for ${F}")
-@typeclass trait Alternative[F[_]] extends NonEmptyAlternative[F] with MonoidK[F] { self =>
+trait Alternative[F[_]] extends NonEmptyAlternative[F] with MonoidK[F] { self =>
// Note: `protected` is only necessary to enforce binary compatibility
// since neither `private` nor `private[cats]` work properly here.
@@ -59,14 +78,14 @@ import scala.annotation.implicitNotFound
/**
* Separate the inner foldable values into the "lefts" and "rights".
- *
+ *
* A variant of [[[separate[G[_,_],A,B](fgab:F[G[A,B]])(implicitFM:cats\.FlatMap[F]* separate]]]
* that is specialized for Fs that have Foldable instances which allows for a single-pass implementation
* (as opposed to {{{separate}}} which is 2-pass).
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val l: List[Either[String, Int]] = List(Right(1), Left("error"))
* scala> Alternative[List].separateFoldable(l)
* res0: (List[String], List[Int]) = (List(error),List(1))
@@ -85,7 +104,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> def even(i: Int): Option[String] = Alternative[Option].guard(i % 2 == 0).as("even")
* scala> even(2)
* res0: Option[String] = Some(even)
@@ -101,14 +120,17 @@ import scala.annotation.implicitNotFound
val F = self
val G = Applicative[G]
}
+
+ def fromIterableOnce[A](as: IterableOnce[A]): F[A] =
+ combineAllK(as.iterator.map(pure(_)))
+
+ final def fromFoldable[G[_]: Foldable, A](as: G[A]): F[A] =
+ fromIterableOnce(Foldable[G].toIterable(as))
}
+@suppressUnusedImportWarningForScalaVersionSpecific
object Alternative {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Alternative]] for `F`.
*/
@@ -152,7 +174,4 @@ object Alternative {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToAlternativeOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
}
diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala
index cd6803e635..7a6c267612 100644
--- a/core/src/main/scala/cats/Applicative.scala
+++ b/core/src/main/scala/cats/Applicative.scala
@@ -1,10 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.arrow.Arrow
import cats.data.Chain
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-import scala.collection.immutable.IndexedSeq
+
+import scala.annotation.tailrec
/**
* Applicative functor.
@@ -16,15 +36,14 @@ import scala.collection.immutable.IndexedSeq
*
* Must obey the laws defined in cats.laws.ApplicativeLaws.
*/
-@implicitNotFound("Could not find an instance of Applicative for ${F}")
-@typeclass trait Applicative[F[_]] extends Apply[F] with InvariantMonoidal[F] { self =>
+trait Applicative[F[_]] extends Apply[F] with InvariantMonoidal[F] { self =>
/**
* `pure` lifts any value into the Applicative Functor.
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> Applicative[Option].pure(10)
* res0: Option[Int] = Some(10)
@@ -40,7 +59,7 @@ import scala.collection.immutable.IndexedSeq
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> Applicative[Option].unit
* res0: Option[Unit] = Some(())
@@ -68,11 +87,61 @@ import scala.collection.immutable.IndexedSeq
*/
def replicateA[A](n: Int, fa: F[A]): F[List[A]] =
if (n <= 0) pure(Nil)
+ else if (n == 1) {
+ // if n == 1 don't incur the penalty two maps: .map(Chain.one(_)).map(_.toList)
+ map(fa)(_ :: Nil)
+ } else {
+ val one = map(fa)(Chain.one(_))
+
+ // invariant: n >= 1
+ @tailrec def loop(fa: F[Chain[A]], n: Int, acc: F[Chain[A]]): F[Chain[A]] =
+ if (n == 1) map2(fa, acc)(_.concat(_))
+ else
+ // n >= 2
+ // so (n >> 1) >= 1 and we are allowed to call loop
+ loop(
+ map2(fa, fa)(_.concat(_)),
+ n >> 1,
+ if ((n & 1) == 1) map2(acc, fa)(_.concat(_)) else acc
+ )
+
+ map(loop(one, n - 1, one))(_.toList)
+ }
+
+ /**
+ * Given `fa` and `n`, apply `fa` `n` times discarding results to return F[Unit].
+ *
+ * Example:
+ * {{{
+ * scala> import cats.data.State
+ *
+ * scala> type Counter[A] = State[Int, A]
+ * scala> val getAndIncrement: Counter[Int] = State { i => (i + 1, i) }
+ * scala> val getAndIncrement5: Counter[Unit] =
+ * | Applicative[Counter].replicateA_(5, getAndIncrement)
+ * scala> getAndIncrement5.run(0).value
+ * res0: (Int, Unit) = (5,())
+ * }}}
+ */
+ def replicateA_[A](n: Int, fa: F[A]): F[Unit] =
+ if (n <= 0) unit
+ else if (n == 1) void(fa)
else {
- map(Chain.traverseViaChain(new IndexedSeq[F[A]] {
- override def length = n
- override def apply(i: Int) = fa
- })(identity)(this))(_.toList)
+ val fvoid = void(fa)
+
+ // invariant: n >= 1
+ @tailrec def loop(fa: F[Unit], n: Int, acc: F[Unit]): F[Unit] =
+ if (n == 1) productR(fa)(acc)
+ else
+ // n >= 2
+ // so (n >> 1) >= 1 and we are allowed to call loop
+ loop(
+ productR(fa)(fa),
+ n >> 1,
+ if ((n & 1) == 1) productR(acc)(fa) else acc
+ )
+
+ loop(fvoid, n - 1, fvoid)
}
/**
@@ -81,7 +150,7 @@ import scala.collection.immutable.IndexedSeq
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val alo = Applicative[List].compose[Option]
*
@@ -105,7 +174,7 @@ import scala.collection.immutable.IndexedSeq
* Example:
* {{{
* scala> import cats.kernel.Comparison
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* // compares strings by alphabetical order
* scala> val alpha: Order[String] = Order[String]
@@ -152,7 +221,7 @@ import scala.collection.immutable.IndexedSeq
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> Applicative[List].unlessA(true)(List(1, 2, 3))
* res0: List[Unit] = List(())
@@ -176,7 +245,7 @@ import scala.collection.immutable.IndexedSeq
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> Applicative[List].whenA(true)(List(1, 2, 3))
* res0: List[Unit] = List((), (), ())
@@ -206,7 +275,7 @@ object Applicative {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.Applicative.catsApplicativeForArrow
* scala> val toLong: Int => Long = _.toLong
* scala> val double: Int => Int = 2*_
@@ -225,7 +294,7 @@ object Applicative {
* Example:
* {{{
* scala> import cats._
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val fa = Some(3)
* fa: Option[Int] = Some(3)
* scala> Applicative.coflatMap[Option].coflatten(fa)
@@ -238,10 +307,6 @@ object Applicative {
def map[A, B](fa: F[A])(f: A => B): F[B] = F.map(fa)(f)
}
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Applicative]] for `F`.
*/
@@ -279,10 +344,6 @@ object Applicative {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToApplicativeOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[cats] class ApplicativeMonoid[F[_], A](f: Applicative[F], monoid: Monoid[A])
diff --git a/core/src/main/scala/cats/ApplicativeError.scala b/core/src/main/scala/cats/ApplicativeError.scala
index d36f8944fe..7582fca4ed 100644
--- a/core/src/main/scala/cats/ApplicativeError.scala
+++ b/core/src/main/scala/cats/ApplicativeError.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.ApplicativeError.CatchOnlyPartiallyApplied
@@ -20,7 +41,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* // integer-rounded division
* scala> def divide[F[_]](dividend: Int, divisor: Int)(implicit F: ApplicativeError[F, String]): F[Int] =
@@ -83,6 +104,27 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
*/
def handleError[A](fa: F[A])(f: E => A): F[A] = handleErrorWith(fa)(f.andThen(pure))
+ /**
+ * Void any error, by mapping it to `Unit`.
+ *
+ * This is useful when errors are reported via a side-channel but not directly handled.
+ * For example in Cats Effect:
+ *
+ * {{{
+ * IO.deferred[OutcomeIO[A]].flatMap { oc =>
+ * ioa.guaranteeCase(oc.complete(_).void).void.voidError.start
+ * // ...
+ * }
+ * }}}
+ *
+ * Without the `.voidError`, the Cats Effect runtime would consider an error in `ioa` to be
+ * unhandled and elevate it to [[scala.concurrent.ExecutionContext.reportFailure ExecutionContext#reportFailure]].
+ *
+ * @see [[handleError]] to map to an `A` value instead of `Unit`.
+ * @see [[https://github.com/typelevel/cats-effect/issues/3152 cats-effect#3152]]
+ */
+ def voidError(fu: F[Unit]): F[Unit] = handleError(fu)(Function.const(()))
+
/**
* Handle errors by turning them into [[scala.util.Either]] values.
*
@@ -116,7 +158,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
* `F[A]` values.
*/
def recover[A](fa: F[A])(pf: PartialFunction[E, A]): F[A] =
- handleErrorWith(fa)(e => (pf.andThen(pure(_))).applyOrElse(e, raiseError[A](_)))
+ handleErrorWith(fa)(e => pf.andThen(pure(_)).applyOrElse(e, raiseError[A](_)))
/**
* Recover from certain errors by mapping them to an `F[A]` value.
@@ -217,7 +259,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
* }}}
*/
def onError[A](fa: F[A])(pf: PartialFunction[E, F[Unit]]): F[A] =
- handleErrorWith(fa)(e => (pf.andThen(map2(_, raiseError[A](e))((_, b) => b))).applyOrElse(e, raiseError))
+ handleErrorWith(fa)(e => pf.andThen(map2(_, raiseError[A](e))((_, b) => b)).applyOrElse(e, raiseError))
/**
* Often E is Throwable. Here we try to call pure or catch
@@ -226,7 +268,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
def catchNonFatal[A](a: => A)(implicit ev: Throwable <:< E): F[A] =
try pure(a)
catch {
- case NonFatal(e) => raiseError(e)
+ case e if NonFatal(e) => raiseError(e)
}
/**
@@ -236,7 +278,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
def catchNonFatalEval[A](a: Eval[A])(implicit ev: Throwable <:< E): F[A] =
try pure(a.value)
catch {
- case NonFatal(e) => raiseError(e)
+ case e if NonFatal(e) => raiseError(e)
}
/**
@@ -280,7 +322,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.ApplicativeError
* scala> val F = ApplicativeError[Either[String, *], String]
*
@@ -302,7 +344,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.ApplicativeError
*
* scala> ApplicativeError[Option, Unit].fromValidated(1.valid[Unit])
@@ -323,7 +365,7 @@ object ApplicativeError {
def apply[F[_], E](implicit F: ApplicativeError[F, E]): ApplicativeError[F, E] = F
final private[cats] class LiftFromOptionPartially[F[_]](private val dummy: Boolean = true) extends AnyVal {
- def apply[E, A](oa: Option[A], ifEmpty: => E)(implicit F: ApplicativeError[F, _ >: E]): F[A] =
+ def apply[E, A](oa: Option[A], ifEmpty: => E)(implicit F: ApplicativeError[F, ? >: E]): F[A] =
oa match {
case Some(a) => F.pure(a)
case None => F.raiseError(ifEmpty)
@@ -346,7 +388,7 @@ object ApplicativeError {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.ApplicativeError
*
* scala> ApplicativeError.liftFromOption[Either[String, *]](Some(1), "Empty")
diff --git a/core/src/main/scala/cats/Apply.scala b/core/src/main/scala/cats/Apply.scala
index b940aa0718..f4ffa1f7f3 100644
--- a/core/src/main/scala/cats/Apply.scala
+++ b/core/src/main/scala/cats/Apply.scala
@@ -1,16 +1,33 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
-import simulacrum.{noop, typeclass}
import cats.data.Ior
-import scala.annotation.implicitNotFound
/**
* Weaker version of Applicative[F]; has apply but not pure.
*
* Must obey the laws defined in cats.laws.ApplyLaws.
*/
-@implicitNotFound("Could not find an instance of Apply for ${F}")
-@typeclass(excludeParents = List("ApplyArityFunctions"))
trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArityFunctions[F] { self =>
/**
@@ -19,7 +36,7 @@ trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArit
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val someF: Option[Int => Long] = Some(_.toLong + 1L)
* scala> val noneF: Option[Int => Long] = None
@@ -48,7 +65,7 @@ trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArit
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.Validated
* scala> import Validated.{Valid, Invalid}
*
@@ -82,7 +99,7 @@ trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArit
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.Validated
* scala> import Validated.{Valid, Invalid}
*
@@ -134,14 +151,14 @@ trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArit
* Alias for [[productR]].
*/
@deprecated("Use *> or productR instead.", "1.0.0-RC2")
- @noop @inline final private[cats] def followedBy[A, B](fa: F[A])(fb: F[B]): F[B] =
+ @inline final private[cats] def followedBy[A, B](fa: F[A])(fb: F[B]): F[B] =
productR(fa)(fb)
/**
* Alias for [[productL]].
*/
@deprecated("Use <* or productL instead.", "1.0.0-RC2")
- @noop @inline final private[cats] def forEffect[A, B](fa: F[A])(fb: F[B]): F[A] =
+ @inline final private[cats] def forEffect[A, B](fa: F[A])(fb: F[B]): F[A] =
productL(fa)(fb)
/**
@@ -157,7 +174,7 @@ trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArit
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val someInt: Option[Int] = Some(3)
* scala> val noneInt: Option[Int] = None
@@ -195,7 +212,7 @@ trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArit
*
* {{{
* scala> import cats.{Eval, Later}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val bomb: Eval[Option[Int]] = Later(sys.error("boom"))
* scala> val x: Option[Int] = None
* scala> x.map2Eval(bomb)(_ + _).value
@@ -210,7 +227,7 @@ trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArit
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val alo = Apply[List].compose[Option]
*
@@ -224,7 +241,6 @@ trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArit
val G = Apply[G]
}
- @noop
@deprecated("Dangerous method, use ifM (a flatMap) or ifF (a map) instead", "2.6.2")
def ifA[A](fcond: F[Boolean])(ifTrue: F[A], ifFalse: F[A]): F[A] = {
def ite(b: Boolean)(ifTrue: A, ifFalse: A) = if (b) ifTrue else ifFalse
@@ -249,10 +265,6 @@ object Apply {
def functor: Functor[F] = Apply[F]
}
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Apply]] for `F`.
*/
@@ -302,10 +314,6 @@ object Apply {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToApplyOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[cats] class ApplySemigroup[F[_], A](f: Apply[F], sg: Semigroup[A]) extends Semigroup[F[A]] {
diff --git a/core/src/main/scala/cats/Bifoldable.scala b/core/src/main/scala/cats/Bifoldable.scala
index b79d737ba2..12b4f7f3dc 100644
--- a/core/src/main/scala/cats/Bifoldable.scala
+++ b/core/src/main/scala/cats/Bifoldable.scala
@@ -1,13 +1,30 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* A type class abstracting over types that give rise to two independent [[cats.Foldable]]s.
*/
-@implicitNotFound("Could not find an instance of Bifoldable for ${F}")
-@typeclass trait Bifoldable[F[_, _]] extends Serializable { self =>
+trait Bifoldable[F[_, _]] extends Serializable { self =>
/**
* Collapse the structure with a left-associative function
@@ -24,7 +41,7 @@ import scala.annotation.implicitNotFound
*
* With syntax extensions, `bifoldLeft` can be used like:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> fab.bifoldLeft(Option(0))((c, a) => c.map(_ + a.head), (c, b) => c.map(_ + b))
* res1: Option[Int] = Some(3)
* }}}
@@ -56,7 +73,7 @@ import scala.annotation.implicitNotFound
*
* With syntax extensions, `bifoldRight` can be used like:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val bifolded2 = fab.bifoldRight(Eval.now(0))((a, c) => c.map(_ + a.head), (b, c) => c.map(_ + b))
* scala> bifolded2.value
* res1: Int = 3
@@ -91,10 +108,6 @@ object Bifoldable extends cats.instances.NTupleBitraverseInstances {
@deprecated("Use catsStdBitraverseForTuple2 in cats.instances.NTupleBitraverseInstances", "2.4.0")
def catsBitraverseForTuple2: Bitraverse[Tuple2] = cats.instances.tuple.catsStdBitraverseForTuple2
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Bifoldable]] for `F`.
*/
@@ -136,10 +149,6 @@ object Bifoldable extends cats.instances.NTupleBitraverseInstances {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToBifoldableOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[cats] trait ComposedBifoldable[F[_, _], G[_, _]] extends Bifoldable[λ[(α, β) => F[G[α, β], G[α, β]]]] {
diff --git a/core/src/main/scala/cats/Bifunctor.scala b/core/src/main/scala/cats/Bifunctor.scala
index fab1d6226c..58915b08bf 100644
--- a/core/src/main/scala/cats/Bifunctor.scala
+++ b/core/src/main/scala/cats/Bifunctor.scala
@@ -1,13 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
/**
* A type class of types which give rise to two independent, covariant
* functors.
*/
-@implicitNotFound("Could not find an instance of Bifunctor for ${F}")
-@typeclass trait Bifunctor[F[_, _]] extends Serializable { self =>
+trait Bifunctor[F[_, _]] extends Serializable { self =>
/**
* The quintessential method of the Bifunctor trait, it applies a
@@ -15,7 +33,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val x: (List[String], Int) = (List("foo", "bar"), 3)
* scala> x.bimap(_.headOption, _.toLong + 1)
@@ -49,7 +67,7 @@ import scala.annotation.implicitNotFound
* Widens A into a supertype AA.
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> sealed trait Foo
* scala> case object Bar extends Foo
* scala> val x1: Either[Bar.type, Int] = Either.left(Bar)
@@ -57,6 +75,20 @@ import scala.annotation.implicitNotFound
* }}}
*/
def leftWiden[A, B, AA >: A](fab: F[A, B]): F[AA, B] = fab.asInstanceOf[F[AA, B]]
+
+ /**
+ * Lift left into F using Applicative.
+ * * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ * scala> val x0: Either[String, Int] = Either.left("foo")
+ * scala> val x1: Either[List[String], Int] = x0.leftLiftTo[List]
+ * }}}
+ *
+ */
+ def leftLiftTo[A, B, C[_]](fab: F[A, B])(implicit C: Applicative[C]): F[C[A], B] =
+ leftMap[A, B, C[A]](fab)(C.pure[A])
+
}
object Bifunctor extends cats.instances.NTupleBifunctorInstances {
@@ -65,10 +97,6 @@ object Bifunctor extends cats.instances.NTupleBifunctorInstances {
@deprecated("Use catsStdBitraverseForTuple2 in cats.instances.NTupleBitraverseInstances", "2.4.0")
def catsBifunctorForTuple2: Bifunctor[Tuple2] = cats.instances.tuple.catsStdBitraverseForTuple2
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Bifunctor]] for `F`.
*/
@@ -92,6 +120,9 @@ object Bifunctor extends cats.instances.NTupleBifunctorInstances {
def bimap[C, D](f: A => C, g: B => D): F[C, D] = typeClassInstance.bimap[A, B, C, D](self)(f, g)
def leftMap[C](f: A => C): F[C, B] = typeClassInstance.leftMap[A, B, C](self)(f)
def leftWiden[C >: A]: F[C, B] = typeClassInstance.leftWiden[A, B, C](self)
+ def leftLiftTo[C[_]](implicit C: Applicative[C]): F[C[A], B] =
+ leftMap[C[A]](C.pure[A])
+
}
trait AllOps[F[_, _], A, B] extends Ops[F, A, B]
trait ToBifunctorOps extends Serializable {
@@ -107,9 +138,6 @@ object Bifunctor extends cats.instances.NTupleBifunctorInstances {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToBifunctorOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
}
private[cats] trait ComposedBifunctor[F[_, _], G[_, _]] extends Bifunctor[λ[(A, B) => F[G[A, B], G[A, B]]]] {
diff --git a/core/src/main/scala/cats/Bimonad.scala b/core/src/main/scala/cats/Bimonad.scala
index 4bf3e3f203..bc6498cb35 100644
--- a/core/src/main/scala/cats/Bimonad.scala
+++ b/core/src/main/scala/cats/Bimonad.scala
@@ -1,17 +1,30 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
-@implicitNotFound("Could not find an instance of Bimonad for ${F}")
-@typeclass trait Bimonad[F[_]] extends Monad[F] with Comonad[F]
+trait Bimonad[F[_]] extends Monad[F] with Comonad[F]
object Bimonad {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Bimonad]] for `F`.
*/
@@ -49,8 +62,4 @@ object Bimonad {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToBimonadOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/Bitraverse.scala b/core/src/main/scala/cats/Bitraverse.scala
index 2b90130de0..91e02e9117 100644
--- a/core/src/main/scala/cats/Bitraverse.scala
+++ b/core/src/main/scala/cats/Bitraverse.scala
@@ -1,20 +1,37 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.{noop, typeclass}
-import scala.annotation.implicitNotFound
+package cats
/**
* A type class abstracting over types that give rise to two independent [[cats.Traverse]]s.
*/
-@implicitNotFound("Could not find an instance of Bitraverse for ${F}")
-@typeclass trait Bitraverse[F[_, _]] extends Bifoldable[F] with Bifunctor[F] { self =>
+trait Bitraverse[F[_, _]] extends Bifoldable[F] with Bifunctor[F] { self =>
/**
* Traverse each side of the structure with the given functions.
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> def parseInt(s: String): Option[Int] = Either.catchOnly[NumberFormatException](s.toInt).toOption
*
@@ -32,7 +49,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val rightSome: Either[Option[String], Option[Int]] = Either.right(Some(3))
* scala> rightSome.bisequence
@@ -72,7 +89,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val intAndString: (Int, String) = (7, "test")
*
@@ -83,7 +100,7 @@ import scala.annotation.implicitNotFound
* res2: Option[(Int, String)] = None
* }}}
*/
- @noop
+
def leftTraverse[G[_], A, B, C](fab: F[A, B])(f: A => G[C])(implicit G: Applicative[G]): G[F[C, B]] =
bitraverse(fab)(f, G.pure(_))
@@ -93,7 +110,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val optionalErrorRight: Either[Option[String], Int] = Either.right(123)
* scala> optionalErrorRight.leftSequence
@@ -108,17 +125,13 @@ import scala.annotation.implicitNotFound
* res3: Option[Either[String,Int]] = None
* }}}
*/
- @noop
+
def leftSequence[G[_], A, B](fgab: F[G[A], B])(implicit G: Applicative[G]): G[F[A, B]] =
bitraverse(fgab)(identity, G.pure(_))
}
object Bitraverse {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Bitraverse]] for `F`.
*/
@@ -160,10 +173,6 @@ object Bitraverse {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToBitraverseOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[cats] trait ComposedBitraverse[F[_, _], G[_, _]]
diff --git a/core/src/main/scala/cats/CoflatMap.scala b/core/src/main/scala/cats/CoflatMap.scala
index d30ea0ea65..d6001c4923 100644
--- a/core/src/main/scala/cats/CoflatMap.scala
+++ b/core/src/main/scala/cats/CoflatMap.scala
@@ -1,15 +1,32 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* `CoflatMap` is the dual of `FlatMap`.
*
* Must obey the laws in cats.laws.CoflatMapLaws
*/
-@implicitNotFound("Could not find an instance of CoflatMap for ${F}")
-@typeclass trait CoflatMap[F[_]] extends Functor[F] {
+trait CoflatMap[F[_]] extends Functor[F] {
/**
* `coflatMap` is the dual of `flatMap` on `FlatMap`. It applies
@@ -18,7 +35,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.CoflatMap
* scala> val fa = Some(3)
* scala> def f(a: Option[Int]): Int = a match {
@@ -36,7 +53,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.CoflatMap
* scala> val fa = Some(3)
* fa: Option[Int] = Some(3)
@@ -50,10 +67,6 @@ import scala.annotation.implicitNotFound
object CoflatMap {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[CoflatMap]] for `F`.
*/
@@ -93,8 +106,4 @@ object CoflatMap {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToCoflatMapOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/CommutativeApplicative.scala b/core/src/main/scala/cats/CommutativeApplicative.scala
index a2ed39e2fe..8f8a0dad2e 100644
--- a/core/src/main/scala/cats/CommutativeApplicative.scala
+++ b/core/src/main/scala/cats/CommutativeApplicative.scala
@@ -1,8 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.kernel.CommutativeMonoid
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
/**
* Commutative Applicative.
@@ -13,8 +32,7 @@ import scala.annotation.implicitNotFound
*
* Must obey the laws defined in cats.laws.CommutativeApplicativeLaws.
*/
-@implicitNotFound("Could not find an instance of CommutativeApplicative for ${F}")
-@typeclass trait CommutativeApplicative[F[_]] extends Applicative[F] with CommutativeApply[F]
+trait CommutativeApplicative[F[_]] extends Applicative[F] with CommutativeApply[F]
object CommutativeApplicative {
def commutativeMonoidFor[F[_]: CommutativeApplicative, A: CommutativeMonoid]: CommutativeMonoid[F[A]] =
@@ -28,10 +46,6 @@ object CommutativeApplicative {
.map2(x, y)(CommutativeMonoid[A].combine)
}
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[CommutativeApplicative]] for `F`.
*/
@@ -71,8 +85,4 @@ object CommutativeApplicative {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToCommutativeApplicativeOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/CommutativeApply.scala b/core/src/main/scala/cats/CommutativeApply.scala
index 151fde4e81..aad8735957 100644
--- a/core/src/main/scala/cats/CommutativeApply.scala
+++ b/core/src/main/scala/cats/CommutativeApply.scala
@@ -1,8 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.kernel.CommutativeSemigroup
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
/**
* Commutative Apply.
@@ -13,20 +32,11 @@ import scala.annotation.implicitNotFound
*
* Must obey the laws defined in cats.laws.CommutativeApplyLaws.
*/
-@implicitNotFound("Could not find an instance of CommutativeApply for ${F}")
-@typeclass trait CommutativeApply[F[_]] extends Apply[F]
+trait CommutativeApply[F[_]] extends Apply[F]
object CommutativeApply {
def commutativeSemigroupFor[F[_]: CommutativeApply, A: CommutativeSemigroup]: CommutativeSemigroup[F[A]] =
- new CommutativeSemigroup[F[A]] {
- override def combine(x: F[A], y: F[A]): F[A] =
- CommutativeApply[F]
- .map2(x, y)(CommutativeSemigroup[A].combine)
- }
-
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
+ CommutativeApply[F].map2(_, _)(CommutativeSemigroup[A].combine)
/**
* Summon an instance of [[CommutativeApply]] for `F`.
@@ -65,8 +75,4 @@ object CommutativeApply {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToCommutativeApplyOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/CommutativeFlatMap.scala b/core/src/main/scala/cats/CommutativeFlatMap.scala
index fd2f227951..ed6f88f41c 100644
--- a/core/src/main/scala/cats/CommutativeFlatMap.scala
+++ b/core/src/main/scala/cats/CommutativeFlatMap.scala
@@ -1,7 +1,25 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* Commutative FlatMap.
@@ -12,15 +30,10 @@ import scala.annotation.implicitNotFound
*
* Must obey the laws defined in cats.laws.CommutativeFlatMapLaws.
*/
-@implicitNotFound("Could not find an instance of CommutativeFlatMap for ${F}")
-@typeclass trait CommutativeFlatMap[F[_]] extends FlatMap[F] with CommutativeApply[F]
+trait CommutativeFlatMap[F[_]] extends FlatMap[F] with CommutativeApply[F]
object CommutativeFlatMap {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[CommutativeFlatMap]] for `F`.
*/
@@ -58,8 +71,4 @@ object CommutativeFlatMap {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToCommutativeFlatMapOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/CommutativeMonad.scala b/core/src/main/scala/cats/CommutativeMonad.scala
index 2c963efaf4..a79b73c1bc 100644
--- a/core/src/main/scala/cats/CommutativeMonad.scala
+++ b/core/src/main/scala/cats/CommutativeMonad.scala
@@ -1,7 +1,25 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* Commutative Monad.
@@ -12,15 +30,10 @@ import scala.annotation.implicitNotFound
*
* Must obey the laws defined in cats.laws.CommutativeMonadLaws.
*/
-@implicitNotFound("Could not find an instance of CommutativeMonad for ${F}")
-@typeclass trait CommutativeMonad[F[_]] extends Monad[F] with CommutativeFlatMap[F] with CommutativeApplicative[F]
+trait CommutativeMonad[F[_]] extends Monad[F] with CommutativeFlatMap[F] with CommutativeApplicative[F]
object CommutativeMonad {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[CommutativeMonad]] for `F`.
*/
@@ -62,8 +75,4 @@ object CommutativeMonad {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToCommutativeMonadOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/Comonad.scala b/core/src/main/scala/cats/Comonad.scala
index 67d5f79a80..2db0275332 100644
--- a/core/src/main/scala/cats/Comonad.scala
+++ b/core/src/main/scala/cats/Comonad.scala
@@ -1,7 +1,25 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* Comonad
@@ -11,8 +29,7 @@ import scala.annotation.implicitNotFound
*
* Must obey the laws defined in cats.laws.ComonadLaws.
*/
-@implicitNotFound("Could not find an instance of Comonad for ${F}")
-@typeclass trait Comonad[F[_]] extends CoflatMap[F] {
+trait Comonad[F[_]] extends CoflatMap[F] {
/**
* `extract` is the dual of `pure` on Monad (via `Applicative`)
@@ -32,10 +49,6 @@ import scala.annotation.implicitNotFound
object Comonad {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Comonad]] for `F`.
*/
@@ -74,8 +87,4 @@ object Comonad {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToComonadOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/Composed.scala b/core/src/main/scala/cats/Composed.scala
index bc607b8a38..42dcb46b72 100644
--- a/core/src/main/scala/cats/Composed.scala
+++ b/core/src/main/scala/cats/Composed.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
private[cats] trait ComposedDistributive[F[_], G[_]] extends Distributive[λ[α => F[G[α]]]] with ComposedFunctor[F, G] {
@@ -25,6 +46,14 @@ private[cats] trait ComposedFunctor[F[_], G[_]] extends Functor[λ[α => F[G[α]
F.map(fga)(ga => G.map(ga)(f))
}
+private[cats] trait ComposedFunctorBifunctor[F[_], G[_, _]] extends Bifunctor[λ[(α, β) => F[G[α, β]]]] { outer =>
+ def F: Functor[F]
+ def G: Bifunctor[G]
+
+ def bimap[W, X, Y, Z](fab: F[G[W, X]])(f: W => Y, g: X => Z): F[G[Y, Z]] =
+ F.map(fab)(G.bimap(_)(f, g))
+}
+
private[cats] trait ComposedApply[F[_], G[_]] extends Apply[λ[α => F[G[α]]]] with ComposedFunctor[F, G] { outer =>
def F: Apply[F]
def G: Apply[G]
@@ -103,6 +132,9 @@ private[cats] trait ComposedTraverse[F[_], G[_]]
override def traverse[H[_]: Applicative, A, B](fga: F[G[A]])(f: A => H[B]): H[F[G[B]]] =
F.traverse(fga)(ga => G.traverse(ga)(f))
+
+ override def mapAccumulate[S, A, B](init: S, fga: F[G[A]])(f: (S, A) => (S, B)): (S, F[G[B]]) =
+ F.mapAccumulate(init, fga)((s, ga) => G.mapAccumulate(s, ga)(f))
}
private[cats] trait ComposedNonEmptyTraverse[F[_], G[_]]
diff --git a/core/src/main/scala/cats/Contravariant.scala b/core/src/main/scala/cats/Contravariant.scala
index b27cc22563..1d7213a20e 100644
--- a/core/src/main/scala/cats/Contravariant.scala
+++ b/core/src/main/scala/cats/Contravariant.scala
@@ -1,12 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
/**
* Must obey the laws defined in cats.laws.ContravariantLaws.
*/
-@implicitNotFound("Could not find an instance of Contravariant for ${F}")
-@typeclass trait Contravariant[F[_]] extends Invariant[F] { self =>
+trait Contravariant[F[_]] extends Invariant[F] { self =>
def contramap[A, B](fa: F[A])(f: B => A): F[B]
override def imap[A, B](fa: F[A])(f: A => B)(fi: B => A): F[B] = contramap(fa)(fi)
@@ -33,10 +51,6 @@ import scala.annotation.implicitNotFound
object Contravariant {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Contravariant]] for `F`.
*/
@@ -76,8 +90,4 @@ object Contravariant {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToContravariantOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/ContravariantMonoidal.scala b/core/src/main/scala/cats/ContravariantMonoidal.scala
index 6889b9657e..d534fe34bb 100644
--- a/core/src/main/scala/cats/ContravariantMonoidal.scala
+++ b/core/src/main/scala/cats/ContravariantMonoidal.scala
@@ -1,7 +1,25 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* [[ContravariantMonoidal]] functors are functors that supply
@@ -12,8 +30,7 @@ import scala.annotation.implicitNotFound
* Based on ekmett's contravariant library:
* https://hackage.haskell.org/package/contravariant-1.4/docs/Data-Functor-Contravariant-Divisible.html
*/
-@implicitNotFound("Could not find an instance of ContravariantMonoidal for ${F}")
-@typeclass trait ContravariantMonoidal[F[_]] extends ContravariantSemigroupal[F] with InvariantMonoidal[F] {
+trait ContravariantMonoidal[F[_]] extends ContravariantSemigroupal[F] with InvariantMonoidal[F] {
/**
* `trivial` produces an instance of `F` for any type `A`
@@ -27,10 +44,6 @@ object ContravariantMonoidal extends SemigroupalArityFunctions {
def monoid[F[_], A](implicit f: ContravariantMonoidal[F]): Monoid[F[A]] =
new ContravariantMonoidalMonoid[F, A](f)
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[ContravariantMonoidal]] for `F`.
*/
@@ -73,10 +86,6 @@ object ContravariantMonoidal extends SemigroupalArityFunctions {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToContravariantMonoidalOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[cats] class ContravariantMonoidalMonoid[F[_], A](f: ContravariantMonoidal[F])
diff --git a/core/src/main/scala/cats/ContravariantSemigroupal.scala b/core/src/main/scala/cats/ContravariantSemigroupal.scala
index cb3346040c..2b9d90e839 100644
--- a/core/src/main/scala/cats/ContravariantSemigroupal.scala
+++ b/core/src/main/scala/cats/ContravariantSemigroupal.scala
@@ -1,14 +1,31 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* [[ContravariantSemigroupal]] is nothing more than something both contravariant
* and Semigroupal. It comes up enough to be useful, and composes well
*/
-@implicitNotFound("Could not find an instance of ContravariantSemigroupal for ${F}")
-@typeclass trait ContravariantSemigroupal[F[_]] extends InvariantSemigroupal[F] with Contravariant[F] { self =>
+trait ContravariantSemigroupal[F[_]] extends InvariantSemigroupal[F] with Contravariant[F] { self =>
override def composeFunctor[G[_]: Functor]: ContravariantSemigroupal[λ[α => F[G[α]]]] =
new ComposedSemigroupal[F, G] {
def F = self
@@ -21,10 +38,6 @@ object ContravariantSemigroupal extends SemigroupalArityFunctions {
def semigroup[F[_], A](implicit f: ContravariantSemigroupal[F]): Semigroup[F[A]] =
new ContravariantSemigroupalSemigroup[F, A](f)
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[ContravariantSemigroupal]] for `F`.
*/
@@ -66,10 +79,6 @@ object ContravariantSemigroupal extends SemigroupalArityFunctions {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToContravariantSemigroupalOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[cats] class ContravariantSemigroupalSemigroup[F[_], A](f: ContravariantSemigroupal[F]) extends Semigroup[F[A]] {
diff --git a/core/src/main/scala/cats/Defer.scala b/core/src/main/scala/cats/Defer.scala
index 9cbfee96ef..a4fd3da24d 100644
--- a/core/src/main/scala/cats/Defer.scala
+++ b/core/src/main/scala/cats/Defer.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import scala.util.control.TailCalls.TailRec
@@ -13,7 +34,7 @@ import scala.util.control.TailCalls.TailRec
* so
* {{{
* scala> import cats._
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> var evaluated = false
* scala> val dfa = Defer[Eval].defer {
@@ -48,15 +69,47 @@ trait Defer[F[_]] extends Serializable {
* of the above F[A] run forever.
*/
def fix[A](fn: F[A] => F[A]): F[A] = {
- lazy val res: F[A] = defer(fn(res))
+ lazy val res: F[A] = fn(defer(res))
res
}
+
+ /**
+ * Useful when you want a recursive function that returns F where
+ * F[_]: Defer. Examples include IO, Eval, or transformers such
+ * as EitherT or OptionT.
+ *
+ * example:
+ *
+ * val sumTo: Int => Eval[Int] =
+ * Defer[Eval].recursiveFn[Int, Int] { recur =>
+ *
+ * { i =>
+ * if (i > 0) recur(i - 1).map(_ + i)
+ * else Eval.now(0)
+ * }
+ * }
+ */
+ def recursiveFn[A, B](fn: (A => F[B]) => (A => F[B])): A => F[B] =
+ new Function1[A, F[B]] { self =>
+ val loopFn: A => F[B] = fn(self)
+
+ def apply(a: A): F[B] = defer(loopFn(a))
+ }
}
object Defer {
def apply[F[_]](implicit defer: Defer[F]): Defer[F] = defer
+ implicit def catsDeferForEq: Defer[Eq] = cats.implicits.catsDeferForEq
+ implicit def catsDeferForEquiv: Defer[Equiv] = cats.implicits.catsDeferForEquiv
implicit def catsDeferForFunction0: Defer[Function0] = cats.instances.function.catsSddDeferForFunction0
implicit def catsDeferForFunction1[A]: Defer[Function1[A, *]] = cats.instances.function.catsStdDeferForFunction1[A]
+ implicit def catsDeferForHash: Defer[Hash] = cats.implicits.catsDeferForHash
+ implicit def catsDeferForOrder: Defer[Order] = cats.instances.order.catsDeferForOrder
+ implicit def catsStdDeferForOrdering: Defer[Ordering] = cats.instances.ordering.catsStdDeferForOrdering
+ implicit def catsDeferForPartialOrder: Defer[PartialOrder] = cats.instances.partialOrder.catsDeferForPartialOrder
+ implicit def catsStdDeferForPartialOrdering: Defer[PartialOrdering] =
+ cats.instances.partialOrdering.catsStdDeferForPartialOrdering
+ implicit def catsDeferForShow: Defer[Show] = cats.implicits.catsDeferForShow
implicit def catsDeferForTailRec: Defer[TailRec] = cats.instances.tailRec.catsInstancesForTailRec
}
diff --git a/core/src/main/scala/cats/Distributive.scala b/core/src/main/scala/cats/Distributive.scala
index d0ee90fb49..aca048e75a 100644
--- a/core/src/main/scala/cats/Distributive.scala
+++ b/core/src/main/scala/cats/Distributive.scala
@@ -1,9 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-@implicitNotFound("Could not find an instance of Distributive for ${F}")
-@typeclass trait Distributive[F[_]] extends Functor[F] { self =>
+trait Distributive[F[_]] extends Functor[F] { self =>
/**
* Given a function which returns a distributive `F`, apply that value across the structure G.
@@ -25,10 +43,6 @@ import scala.annotation.implicitNotFound
object Distributive {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Distributive]] for `F`.
*/
@@ -66,8 +80,4 @@ object Distributive {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToDistributiveOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/Eval.scala b/core/src/main/scala/cats/Eval.scala
index 3b52cfcb22..83e387bc08 100644
--- a/core/src/main/scala/cats/Eval.scala
+++ b/core/src/main/scala/cats/Eval.scala
@@ -1,5 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
+import org.typelevel.scalaccompat.annotation.uncheckedVariance2
+
import scala.annotation.tailrec
/**
@@ -81,20 +104,20 @@ sealed abstract class Eval[+A] extends Serializable { self =>
new Eval.FlatMap[B] {
type Start = A
val start = () => c.run(s)
- val run = f
+ val run: (Start => Eval[B]) @uncheckedVariance2 = f
}
}
case c: Eval.Defer[A] =>
new Eval.FlatMap[B] {
type Start = A
val start = c.thunk
- val run = f
+ val run: (Start => Eval[B]) @uncheckedVariance2 = f
}
case _ =>
new Eval.FlatMap[B] {
type Start = A
val start = () => self
- val run = f
+ val run: (Start => Eval[B]) @uncheckedVariance2 = f
}
}
@@ -116,7 +139,7 @@ sealed abstract class Eval[+A] extends Serializable { self =>
* This type should be used when an A value is already in hand, or
* when the computation to produce an A value is pure and very fast.
*/
-final case class Now[A](value: A) extends Eval.Leaf[A] {
+final case class Now[+A](value: A) extends Eval.Leaf[A] {
def memoize: Eval[A] = this
}
@@ -134,7 +157,7 @@ final case class Now[A](value: A) extends Eval.Leaf[A] {
* by the closure) will not be retained, and will be available for
* garbage collection.
*/
-final class Later[A](f: () => A) extends Eval.Leaf[A] {
+final class Later[+A](f: () => A) extends Eval.Leaf[A] {
private[this] var thunk: () => A = f
// The idea here is that `f` may have captured very large
@@ -167,7 +190,7 @@ object Later {
* required. It should be avoided except when laziness is required and
* caching must be avoided. Generally, prefer Later.
*/
-final class Always[A](f: () => A) extends Eval.Leaf[A] {
+final class Always[+A](f: () => A) extends Eval.Leaf[A] {
def value: A = f()
def memoize: Eval[A] = new Later(f)
}
@@ -183,7 +206,7 @@ object Eval extends EvalInstances {
* so calling .value does not trigger
* any flatMaps or defers
*/
- sealed abstract class Leaf[A] extends Eval[A]
+ sealed abstract class Leaf[+A] extends Eval[A]
/**
* Construct an eager Eval[A] value (i.e. Now[A]).
@@ -366,7 +389,7 @@ object Eval extends EvalInstances {
sealed abstract private[cats] class EvalInstances extends EvalInstances0 {
- implicit val catsBimonadForEval: Bimonad[Eval] with CommutativeMonad[Eval] =
+ implicit val catsBimonadForEval: Bimonad[Eval] & CommutativeMonad[Eval] =
new Bimonad[Eval] with StackSafeMonad[Eval] with CommutativeMonad[Eval] {
override def map[A, B](fa: Eval[A])(f: A => B): Eval[B] = fa.map(f)
def pure[A](a: A): Eval[A] = Now(a)
@@ -410,10 +433,7 @@ sealed abstract private[cats] class EvalInstances extends EvalInstances0 {
}
implicit def catsOrderForEval[A: Order]: Order[Eval[A]] =
- new Order[Eval[A]] {
- def compare(lx: Eval[A], ly: Eval[A]): Int =
- Order[A].compare(lx.value, ly.value)
- }
+ Order.by(_.value)
implicit def catsGroupForEval[A: Group]: Group[Eval[A]] =
new EvalGroup[A] { val algebra: Group[A] = Group[A] }
@@ -437,10 +457,7 @@ sealed abstract private[cats] class EvalInstances extends EvalInstances0 {
sealed abstract private[cats] class EvalInstances0 extends EvalInstances1 {
implicit def catsPartialOrderForEval[A: PartialOrder]: PartialOrder[Eval[A]] =
- new PartialOrder[Eval[A]] {
- def partialCompare(lx: Eval[A], ly: Eval[A]): Double =
- PartialOrder[A].partialCompare(lx.value, ly.value)
- }
+ PartialOrder.by(_.value)
implicit def catsMonoidForEval[A: Monoid]: Monoid[Eval[A]] =
new EvalMonoid[A] { val algebra = Monoid[A] }
@@ -448,10 +465,7 @@ sealed abstract private[cats] class EvalInstances0 extends EvalInstances1 {
sealed abstract private[cats] class EvalInstances1 {
implicit def catsEqForEval[A: Eq]: Eq[Eval[A]] =
- new Eq[Eval[A]] {
- def eqv(lx: Eval[A], ly: Eval[A]): Boolean =
- Eq[A].eqv(lx.value, ly.value)
- }
+ Eq.by(_.value)
implicit def catsSemigroupForEval[A: Semigroup]: Semigroup[Eval[A]] =
new EvalSemigroup[A] { val algebra = Semigroup[A] }
diff --git a/core/src/main/scala/cats/FlatMap.scala b/core/src/main/scala/cats/FlatMap.scala
index 6eaba3b5d3..1adeb60fa3 100644
--- a/core/src/main/scala/cats/FlatMap.scala
+++ b/core/src/main/scala/cats/FlatMap.scala
@@ -1,8 +1,25 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import simulacrum.noop
-import scala.annotation.implicitNotFound
+package cats
/**
* FlatMap type class gives us flatMap, which allows us to have a value
@@ -19,8 +36,7 @@ import scala.annotation.implicitNotFound
*
* Must obey the laws defined in cats.laws.FlatMapLaws.
*/
-@implicitNotFound("Could not find an instance of FlatMap for ${F}")
-@typeclass trait FlatMap[F[_]] extends Apply[F] {
+trait FlatMap[F[_]] extends Apply[F] with FlatMapArityFunctions[F] {
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
/**
@@ -31,7 +47,7 @@ import scala.annotation.implicitNotFound
* Example:
* {{{
* scala> import cats.Eval
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val nested: Eval[Eval[Int]] = Eval.now(Eval.now(3))
* scala> val flattened: Eval[Int] = nested.flatten
@@ -49,7 +65,7 @@ import scala.annotation.implicitNotFound
*
* {{{
* scala> import cats.Eval
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val fa: Option[Int] = Some(3)
* scala> def fb: Option[String] = Some("foo")
* scala> fa.productREval(Eval.later(fb))
@@ -59,7 +75,7 @@ import scala.annotation.implicitNotFound
def productREval[A, B](fa: F[A])(fb: Eval[F[B]]): F[B] = flatMap(fa)(_ => fb.value)
@deprecated("Use productREval instead.", "1.0.0-RC2")
- @noop private[cats] def followedByEval[A, B](fa: F[A])(fb: Eval[F[B]]): F[B] = productREval(fa)(fb)
+ private[cats] def followedByEval[A, B](fa: F[A])(fb: Eval[F[B]]): F[B] = productREval(fa)(fb)
/**
* Sequentially compose two actions, discarding any value produced by the second. This variant of
@@ -68,7 +84,7 @@ import scala.annotation.implicitNotFound
*
* {{{
* scala> import cats.Eval
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> var count = 0
* scala> val fa: Option[Int] = Some(3)
* scala> def fb: Option[Unit] = Some(count += 1)
@@ -83,7 +99,7 @@ import scala.annotation.implicitNotFound
def productLEval[A, B](fa: F[A])(fb: Eval[F[B]]): F[A] = flatMap(fa)(a => as(fb.value, a))
@deprecated("Use productLEval instead.", "1.0.0-RC2")
- @noop private[cats] def forEffectEval[A, B](fa: F[A])(fb: Eval[F[B]]): F[A] = productLEval(fa)(fb)
+ private[cats] def forEffectEval[A, B](fa: F[A])(fb: Eval[F[B]]): F[A] = productLEval(fa)(fb)
override def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] =
flatMap(ff)(f => map(fa)(f))
@@ -111,7 +127,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> List("12", "34", "56").mproduct(_.toList)
* res0: List[(String, Char)] = List((12,1), (12,2), (34,3), (34,4), (56,5), (56,6))
* }}}
@@ -122,7 +138,7 @@ import scala.annotation.implicitNotFound
/**
* `if` lifted into monad.
*/
- @noop
+
def ifM[B](fa: F[Boolean])(ifTrue: => F[B], ifFalse: => F[B]): F[B] =
flatMap(fa)(if (_) ifTrue else ifFalse)
@@ -168,7 +184,7 @@ import scala.annotation.implicitNotFound
* allocating single element lists, but if we have a k > 1, we will allocate
* exponentially increasing memory and very quickly OOM.
*/
- @noop
+
def foreverM[A, B](fa: F[A]): F[B] = {
// allocate two things once for efficiency.
val leftUnit = Left(())
@@ -181,7 +197,7 @@ import scala.annotation.implicitNotFound
* A may be some state, we may take the current state, run some effect to get
* a new state and repeat.
*/
- @noop
+
def iterateForeverM[A, B](a: A)(f: A => F[A]): F[B] =
tailRecM[A, B](a)(f.andThen { fa =>
map(fa)(Left(_): Either[A, B])
@@ -192,7 +208,7 @@ import scala.annotation.implicitNotFound
* for polling type operations on State (or RNG) Monads, or in effect
* monads.
*/
- @noop
+
def untilDefinedM[A](foa: F[Option[A]]): F[A] = {
val leftUnit: Either[Unit, A] = Left(())
val feither: F[Either[Unit, A]] = map(foa) {
@@ -205,10 +221,6 @@ import scala.annotation.implicitNotFound
object FlatMap {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[FlatMap]] for `F`.
*/
@@ -252,8 +264,4 @@ object FlatMap {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToFlatMapOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/Foldable.scala b/core/src/main/scala/cats/Foldable.scala
index 7616bd7d76..843ac1a25f 100644
--- a/core/src/main/scala/cats/Foldable.scala
+++ b/core/src/main/scala/cats/Foldable.scala
@@ -1,11 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import scala.collection.mutable
import cats.kernel.CommutativeMonoid
-import simulacrum.{noop, typeclass}
-import Foldable.{sentinel, Source}
-import scala.annotation.implicitNotFound
+import Foldable.{sentinel, Source}
/**
* Data structures that can be folded to a summary value.
@@ -29,8 +48,6 @@ import scala.annotation.implicitNotFound
*
* See: [[http://www.cs.nott.ac.uk/~pszgmh/fold.pdf A tutorial on the universality and expressiveness of fold]]
*/
-@implicitNotFound("Could not find an instance of Foldable for ${F}")
-@typeclass(excludeParents = List("FoldableNFunctions"))
trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { self =>
/**
@@ -143,7 +160,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val l = List(6, 3, 2)
* This is equivalent to (6 - 3) - 2
* scala> Foldable[List].reduceLeftOption(l)(_ - _)
@@ -171,7 +188,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val l = List(6, 3, 2)
* This is equivalent to 6 - (3 - 2)
* scala> Foldable[List].reduceRightOption(l)((current, rest) => rest.map(current - _)).value
@@ -327,7 +344,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* Like `collectFirst` from `scala.collection.Traversable` but takes `A => Option[B]`
* instead of `PartialFunction`s.
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val keys = List(1, 2, 4, 5)
* scala> val map = Map(4 -> "Four", 5 -> "Five")
* scala> keys.collectFirstSome(map.get)
@@ -351,7 +368,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
*
* For example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> def parseInt(s: String): Either[String, Int] = Either.catchOnly[NumberFormatException](s.toInt).leftMap(_.getMessage)
* scala> val keys1 = List("1", "2", "4", "5")
* scala> val map1 = Map(4 -> "Four", 5 -> "Five")
@@ -371,7 +388,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* res3: scala.util.Either[String,Option[String]] = Right(Some(Four))
* }}}
*/
- @noop
+
def collectFirstSomeM[G[_], A, B](fa: F[A])(f: A => G[Option[B]])(implicit G: Monad[G]): G[Option[B]] =
G.tailRecM(Foldable.Source.fromFoldable(fa)(self))(_.uncons match {
case Some((a, src)) =>
@@ -385,20 +402,20 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
/**
* Tear down a subset of this structure using a `PartialFunction`.
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val xs = List(1, 2, 3, 4)
* scala> Foldable[List].collectFold(xs) { case n if n % 2 == 0 => n }
* res0: Int = 6
* }}}
*/
- @noop
+
def collectFold[A, B](fa: F[A])(f: PartialFunction[A, B])(implicit B: Monoid[B]): B =
foldLeft(fa, B.empty)((acc, a) => B.combine(acc, f.applyOrElse(a, (_: A) => B.empty)))
/**
* Tear down a subset of this structure using a `A => Option[M]`.
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val xs = List(1, 2, 3, 4)
* scala> def f(n: Int): Option[Int] = if (n % 2 == 0) Some(n) else None
* scala> Foldable[List].collectFoldSome(xs)(f)
@@ -474,15 +491,13 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* For example:
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val F = Foldable[List]
* scala> F.foldA(List(Either.right[String, Int](1), Either.right[String, Int](2)))
* res0: Either[String, Int] = Right(3)
* }}}
- *
- * See [[https://github.com/typelevel/simulacrum/issues/162 this issue]] for an explanation of `@noop` usage.
*/
- @noop def foldA[G[_], A](fga: F[G[A]])(implicit G: Applicative[G], A: Monoid[A]): G[A] =
+ def foldA[G[_], A](fga: F[G[A]])(implicit G: Applicative[G], A: Monoid[A]): G[A] =
foldMapA(fga)(identity)
/**
@@ -497,7 +512,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* a: String = "foo321"
* }}}
*/
- @noop
+
def foldMapK[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: MonoidK[G]): G[B] =
foldRight(fa, Eval.now(G.empty[B])) { (a, evalGb) =>
G.combineKEval(f(a), evalGb)
@@ -517,7 +532,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
*
* {{{
* scala> import cats.Foldable
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val evenNumbers = List(2,4,6,8,10)
* scala> val evenOpt: Int => Option[Int] =
* | i => if (i % 2 == 0) Some(i) else None
@@ -538,7 +553,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
*
* {{{
* scala> import cats.Foldable
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val evenNumbers = List(2,4,6,8,10)
* scala> val evenOpt: Int => Option[Int] =
* | i => if (i % 2 == 0) Some(i) else None
@@ -560,12 +575,12 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* For example:
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> def parseInt(s: String): Option[Int] = Either.catchOnly[NumberFormatException](s.toInt).toOption
* scala> val F = Foldable[List]
- * scala> F.traverse_(List("333", "444"))(parseInt)
+ * scala> F.traverseVoid(List("333", "444"))(parseInt)
* res0: Option[Unit] = Some(())
- * scala> F.traverse_(List("333", "zzz"))(parseInt)
+ * scala> F.traverseVoid(List("333", "zzz"))(parseInt)
* res1: Option[Unit] = None
* }}}
*
@@ -573,32 +588,48 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* or effect, and the specific `A` aspect of `G[A]` is not otherwise
* needed.
*/
- def traverse_[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] =
- foldRight(fa, Always(G.pure(()))) { (a, acc) =>
+ def traverseVoid[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] =
+ foldRight(fa, Always(G.unit)) { (a, acc) =>
G.map2Eval(f(a), acc) { (_, _) =>
()
}
}.value
+ /**
+ * Alias for `traverseVoid`.
+ *
+ * @deprecated this method should be considered as deprecated and replaced by `traverseVoid`.
+ */
+ def traverse_[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] =
+ traverseVoid(fa)(f)
+
/**
* Sequence `F[G[A]]` using `Applicative[G]`.
*
- * This is similar to `traverse_` except it operates on `F[G[A]]`
+ * This is similar to `traverseVoid` except it operates on `F[G[A]]`
* values, so no additional functions are needed.
*
* For example:
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val F = Foldable[List]
- * scala> F.sequence_(List(Option(1), Option(2), Option(3)))
+ * scala> F.sequenceVoid(List(Option(1), Option(2), Option(3)))
* res0: Option[Unit] = Some(())
- * scala> F.sequence_(List(Option(1), None, Option(3)))
+ * scala> F.sequenceVoid(List(Option(1), None, Option(3)))
* res1: Option[Unit] = None
* }}}
*/
+ def sequenceVoid[G[_]: Applicative, A](fga: F[G[A]]): G[Unit] =
+ traverseVoid(fga)(identity)
+
+ /**
+ * Alias for `sequenceVoid`.
+ *
+ * @deprecated this method should be considered as deprecated and replaced by `sequenceVoid`.
+ */
def sequence_[G[_]: Applicative, A](fga: F[G[A]]): G[Unit] =
- traverse_(fga)(identity)
+ sequenceVoid(fga)
/**
* Fold implemented using the given `MonoidK[G]` instance.
@@ -609,7 +640,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* For example:
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val F = Foldable[List]
* scala> F.foldK(List(1 :: 2 :: Nil, 3 :: 4 :: 5 :: Nil))
* res0: List[Int] = List(1, 2, 3, 4, 5)
@@ -632,7 +663,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
*
* For example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val list = List(1,2,3,4)
* scala> Foldable[List].findM(list)(n => (n >= 2).asRight[String])
* res0: Either[String,Option[Int]] = Right(Some(2))
@@ -647,7 +678,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* res3: Either[String,Option[Int]] = Left(error)
* }}}
*/
- @noop
+
def findM[G[_], A](fa: F[A])(p: A => G[Boolean])(implicit G: Monad[G]): G[Option[A]] =
G.tailRecM(Foldable.Source.fromFoldable(fa)(self))(_.uncons match {
case Some((a, src)) => G.map(p(a))(if (_) Right(Some(a)) else Left(src.value))
@@ -679,7 +710,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* For example:
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val F = Foldable[List]
* scala> F.existsM(List(1,2,3,4))(n => Option(n <= 4))
* res0: Option[Boolean] = Some(true)
@@ -714,7 +745,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* For example:
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val F = Foldable[List]
* scala> F.forallM(List(1,2,3,4))(n => Option(n <= 4))
* res0: Option[Boolean] = Some(true)
@@ -753,7 +784,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* Equivalent to `Functor#map` and then `Alternative#separate`.
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val list = List(1,2,3,4)
* scala> Foldable[List].partitionEither(list)(a => if (a % 2 == 0) Left(a.toString) else Right(a))
* res0: (List[String], List[Int]) = (List(2, 4),List(1, 3))
@@ -810,7 +841,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* Intercalate/insert an element between the existing elements while folding.
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> Foldable[List].intercalate(List("a","b","c"), "-")
* res0: String = a-b-c
* scala> Foldable[List].intercalate(List("a"), "-")
@@ -856,7 +887,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* Equivalent to `Functor#map` and then `Alternative#separate`.
*
* {{{
- * scala> import cats.implicits._, cats.Foldable, cats.data.Const
+ * scala> import cats.syntax.all._, cats.Foldable, cats.data.Const
* scala> val list = List(1,2,3,4)
* scala> Foldable[List].partitionBifold(list)(a => ("value " + a.toString(), if (a % 2 == 0) -a else a))
* res0: (List[String], List[Int]) = (List(value 1, value 2, value 3, value 4),List(1, -2, 3, -4))
@@ -864,7 +895,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* res1: (List[Int], List[Nothing with Any]) = (List(1, 2, 3, 4),List())
* }}}
*/
- @noop
+
def partitionBifold[H[_, _], A, B, C](
fa: F[A]
)(f: A => H[B, C])(implicit A: Alternative[F], H: Bifoldable[H]): (F[B], F[C]) = {
@@ -883,14 +914,14 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* Equivalent to `Traverse#traverse` over `Alternative#separate`
*
* {{{
- * scala> import cats.implicits._, cats.Foldable, cats.data.Const
+ * scala> import cats.syntax.all._, cats.Foldable, cats.data.Const
* scala> val list = List(1,2,3,4)
* `Const`'s second parameter is never instantiated, so we can use an impossible type:
* scala> Foldable[List].partitionBifoldM(list)(a => Option(Const[Int, Nothing with Any](a)))
* res0: Option[(List[Int], List[Nothing with Any])] = Some((List(1, 2, 3, 4),List()))
* }}}
*/
- @noop
+
def partitionBifoldM[G[_], H[_, _], A, B, C](
fa: F[A]
)(f: A => G[H[B, C]])(implicit A: Alternative[F], M: Monad[G], H: Bifoldable[H]): G[(F[B], F[C])] = {
@@ -911,7 +942,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* Equivalent to `Traverse#traverse` over `Alternative#separate`
*
* {{{
- * scala> import cats.implicits._, cats.Foldable, cats.Eval
+ * scala> import cats.syntax.all._, cats.Foldable, cats.Eval
* scala> val list = List(1,2,3,4)
* scala> val partitioned1 = Foldable[List].partitionEitherM(list)(a => if (a % 2 == 0) Eval.now(Either.left[String, Int](a.toString)) else Eval.now(Either.right[String, Int](a)))
* Since `Eval.now` yields a lazy computation, we need to force it to inspect the result:
@@ -922,7 +953,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
* res1: (List[Nothing], List[Int]) = (List(),List(4, 8, 12, 16))
* }}}
*/
- @noop
+
def partitionEitherM[G[_], A, B, C](
fa: F[A]
)(f: A => G[Either[B, C]])(implicit A: Alternative[F], M: Monad[G]): G[(F[B], F[C])] = {
@@ -932,7 +963,9 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
}
object Foldable {
- private val sentinel: Function1[Any, Any] = new scala.runtime.AbstractFunction1[Any, Any] { def apply(a: Any) = this }
+ private val sentinel: Function1[Any, Any] = new scala.runtime.AbstractFunction1[Any, Any] {
+ def apply(a: Any): Any = this
+ }
def iterateRight[A, B](iterable: Iterable[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = {
def loop(it: Iterator[A]): Eval[B] =
@@ -964,22 +997,18 @@ object Foldable {
private[cats] object Source {
val Empty: Source[Nothing] = new Source[Nothing] {
- def uncons = None
+ def uncons: Option[(Nothing, Eval[Source[Nothing]])] = None
}
def cons[A](a: A, src: Eval[Source[A]]): Source[A] =
new Source[A] {
- def uncons = Some((a, src))
+ def uncons: Option[(A, Eval[Source[A]])] = Some((a, src))
}
def fromFoldable[F[_], A](fa: F[A])(implicit F: Foldable[F]): Source[A] =
F.foldRight[A, Source[A]](fa, Now(Empty))((a, evalSrc) => Later(cons(a, evalSrc))).value
}
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Foldable]] for `F`.
*/
@@ -1040,10 +1069,17 @@ object Foldable {
typeClassInstance.foldMapM[G, A, B](self)(f)(G, B)
def foldMapA[G[_], B](f: A => G[B])(implicit G: Applicative[G], B: Monoid[B]): G[B] =
typeClassInstance.foldMapA[G, A, B](self)(f)(G, B)
+ def traverseVoid[G[_], B](f: A => G[B])(implicit G: Applicative[G]): G[Unit] =
+ typeClassInstance.traverseVoid[G, A, B](self)(f)(G)
def traverse_[G[_], B](f: A => G[B])(implicit G: Applicative[G]): G[Unit] =
- typeClassInstance.traverse_[G, A, B](self)(f)(G)
+ traverseVoid[G, B](f)
+ // TODO: looks like these two methods below duplicate the same named methods from `NestedFoldableOps`.
+ // Moreover, the other two methods take precedence, thereby these two are not in use whatsoever.
+ // Perhaps it makes sense to deprecate one pair of them either here or there.
+ def sequenceVoid[G[_], B](implicit ev$1: A <:< G[B], ev$2: Applicative[G]): G[Unit] =
+ typeClassInstance.sequenceVoid[G, B](self.asInstanceOf[F[G[B]]])
def sequence_[G[_], B](implicit ev$1: A <:< G[B], ev$2: Applicative[G]): G[Unit] =
- typeClassInstance.sequence_[G, B](self.asInstanceOf[F[G[B]]])
+ sequenceVoid[G, B]
def foldK[G[_], B](implicit ev$1: A <:< G[B], G: MonoidK[G]): G[B] =
typeClassInstance.foldK[G, B](self.asInstanceOf[F[G[B]]])(G)
def find(f: A => Boolean): Option[A] = typeClassInstance.find[A](self)(f)
@@ -1075,8 +1111,4 @@ object Foldable {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToFoldableOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/Functor.scala b/core/src/main/scala/cats/Functor.scala
index e17658d731..dbfd70cd0b 100644
--- a/core/src/main/scala/cats/Functor.scala
+++ b/core/src/main/scala/cats/Functor.scala
@@ -1,7 +1,25 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.{noop, typeclass}
-import scala.annotation.implicitNotFound
+package cats
/**
* Functor.
@@ -10,8 +28,7 @@ import scala.annotation.implicitNotFound
*
* Must obey the laws defined in cats.laws.FunctorLaws.
*/
-@implicitNotFound("Could not find an instance of Functor for ${F}")
-@typeclass trait Functor[F[_]] extends Invariant[F] { self =>
+trait Functor[F[_]] extends Invariant[F] { self =>
def map[A, B](fa: F[A])(f: A => B): F[B]
override def imap[A, B](fa: F[A])(f: A => B)(g: B => A): F[B] = map(fa)(f)
@@ -24,7 +41,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val m: Map[Int, String] = Map(1 -> "hi", 2 -> "there", 3 -> "you")
*
@@ -47,12 +64,11 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.Functor
- * scala> import cats.implicits.catsStdInstancesForOption
+ * scala> import cats.syntax.all._
*
- * scala> val s = Some(42)
- * scala> Functor[Option].widen(s)
- * res0: Option[Int] = Some(42)
+ * scala> val l = List(Some(42))
+ * scala> l.widen[Option[Int]]
+ * res0: List[Option[Int]] = List(Some(42))
* }}}
*/
def widen[A, B >: A](fa: F[A]): F[B] = fa.asInstanceOf[F[B]]
@@ -63,7 +79,7 @@ import scala.annotation.implicitNotFound
* Example:
* {{{
* scala> import cats.Functor
- * scala> import cats.implicits.catsStdInstancesForOption
+ * scala> import cats.syntax.all._
*
* scala> val o = Option(42)
* scala> Functor[Option].lift((x: Int) => x + 10)(o)
@@ -77,10 +93,9 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.Functor
- * scala> import cats.implicits.catsStdInstancesForList
+ * scala> import cats.syntax.all._
*
- * scala> Functor[List].void(List(1,2,3))
+ * scala> List(1,2,3).void
* res0: List[Unit] = List((), (), ())
* }}}
*/
@@ -92,10 +107,9 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.Functor
- * scala> import cats.implicits.catsStdInstancesForOption
+ * scala> import cats.syntax.all._
*
- * scala> Functor[Option].fproduct(Option(42))(_.toString)
+ * scala> Option(42).fproduct(_.toString)
* res0: Option[(Int, String)] = Some((42,42))
* }}}
*/
@@ -106,10 +120,9 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.Functor
- * scala> import cats.implicits.catsStdInstancesForOption
+ * scala> import cats.syntax.all._
*
- * scala> Functor[Option].fproductLeft(Option(42))(_.toString)
+ * scala> Option(42).fproductLeft(_.toString)
* res0: Option[(String, Int)] = Some((42,42))
* }}}
*/
@@ -121,10 +134,9 @@ import scala.annotation.implicitNotFound
* Example:
*
* {{{
- * scala> import cats.Functor
- * scala> import cats.implicits.catsStdInstancesForList
+ * scala> import cats.syntax.all._
*
- * scala> Functor[List].as(List(1,2,3), "hello")
+ * scala> List(1,2,3).as("hello")
* res0: List[String] = List(hello, hello, hello)
* }}}
*/
@@ -136,10 +148,9 @@ import scala.annotation.implicitNotFound
* Example:
* {{{
* scala> import scala.collection.immutable.Queue
- * scala> import cats.Functor
- * scala> import cats.implicits.catsStdInstancesForQueue
+ * scala> import cats.syntax.all._
*
- * scala> Functor[Queue].tupleLeft(Queue("hello", "world"), 42)
+ * scala> Queue("hello", "world").tupleLeft(42)
* res0: scala.collection.immutable.Queue[(Int, String)] = Queue((42,hello), (42,world))
* }}}
*/
@@ -151,15 +162,26 @@ import scala.annotation.implicitNotFound
* Example:
* {{{
* scala> import scala.collection.immutable.Queue
- * scala> import cats.Functor
- * scala> import cats.implicits.catsStdInstancesForQueue
+ * scala> import cats.syntax.all._
*
- * scala> Functor[Queue].tupleRight(Queue("hello", "world"), 42)
+ * scala> Queue("hello", "world").tupleRight(42)
* res0: scala.collection.immutable.Queue[(String, Int)] = Queue((hello,42), (world,42))
* }}}
*/
def tupleRight[A, B](fa: F[A], b: B): F[(A, B)] = map(fa)(a => (a, b))
+ /**
+ * Modifies the `A` value in `F[A]` with the supplied function, if the function is defined for the value.
+ * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ *
+ * scala> List(1, 2, 3).mapOrKeep { case 2 => 42 }
+ * res0: List[Int] = List(1, 42, 3)
+ * }}}
+ */
+ def mapOrKeep[A, A1 >: A](fa: F[A])(pf: PartialFunction[A, A1]): F[A1] = map(fa)(a => pf.applyOrElse(a, identity[A1]))
+
/**
* Un-zips an `F[(A, B)]` consisting of element pairs or Tuple2 into two separate F's tupled.
*
@@ -167,13 +189,12 @@ import scala.annotation.implicitNotFound
*
* {{{
* scala> import cats.Functor
- * scala> import cats.implicits.catsStdInstancesForList
+ * scala> import cats.syntax.all._
*
* scala> Functor[List].unzip(List((1,2), (3, 4)))
* res0: (List[Int], List[Int]) = (List(1, 3),List(2, 4))
* }}}
*/
- @noop
def unzip[A, B](fab: F[(A, B)]): (F[A], F[B]) = (map(fab)(_._1), map(fab)(_._2))
/**
@@ -182,13 +203,12 @@ import scala.annotation.implicitNotFound
* Example:
* {{{
* scala> import cats.Functor
- * scala> import cats.implicits.catsStdInstancesForList
+ * scala> import cats.syntax.all._
*
* scala> Functor[List].ifF(List(true, false, false))(1, 0)
* res0: List[Int] = List(1, 0, 0)
* }}}
*/
- @noop
def ifF[A](fb: F[Boolean])(ifTrue: => A, ifFalse: => A): F[A] = map(fb)(x => if (x) ifTrue else ifFalse)
def compose[G[_]: Functor]: Functor[λ[α => F[G[α]]]] =
@@ -197,6 +217,12 @@ import scala.annotation.implicitNotFound
val G = Functor[G]
}
+ def composeBifunctor[G[_, _]: Bifunctor]: Bifunctor[λ[(α, β) => F[G[α, β]]]] =
+ new ComposedFunctorBifunctor[F, G] {
+ val F = self
+ val G = Bifunctor[G]
+ }
+
override def composeContravariant[G[_]: Contravariant]: Contravariant[λ[α => F[G[α]]]] =
new ComposedCovariantContravariant[F, G] {
val F = self
@@ -206,10 +232,6 @@ import scala.annotation.implicitNotFound
object Functor {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Functor]] for `F`.
*/
@@ -239,6 +261,7 @@ object Functor {
def as[B](b: B): F[B] = typeClassInstance.as[A, B](self, b)
def tupleLeft[B](b: B): F[(B, A)] = typeClassInstance.tupleLeft[A, B](self, b)
def tupleRight[B](b: B): F[(A, B)] = typeClassInstance.tupleRight[A, B](self, b)
+ def mapOrKeep[A1 >: A](pf: PartialFunction[A, A1]): F[A1] = typeClassInstance.mapOrKeep[A, A1](self)(pf)
}
trait AllOps[F[_], A] extends Ops[F, A] with Invariant.AllOps[F, A] {
type TypeClassType <: Functor[F]
@@ -256,8 +279,4 @@ object Functor {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToFunctorOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/FunctorFilter.scala b/core/src/main/scala/cats/FunctorFilter.scala
index 275f8bb172..df13f9a734 100644
--- a/core/src/main/scala/cats/FunctorFilter.scala
+++ b/core/src/main/scala/cats/FunctorFilter.scala
@@ -1,14 +1,32 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import scala.collection.immutable.{Queue, Seq, SortedMap}
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
/**
* `FunctorFilter[F]` allows you to `map` and filter out elements simultaneously.
*/
-@implicitNotFound("Could not find an instance of FunctorFilter for ${F}")
-@typeclass
+
trait FunctorFilter[F[_]] extends Serializable {
def functor: Functor[F]
@@ -19,7 +37,7 @@ trait FunctorFilter[F[_]] extends Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val m: Map[Int, String] = Map(1 -> "one", 3 -> "three")
* scala> val l: List[Int] = List(1, 2, 3, 4)
* scala> def asString(i: Int): Option[String] = m.get(i)
@@ -35,7 +53,7 @@ trait FunctorFilter[F[_]] extends Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val l: List[Int] = List(1, 2, 3, 4)
* scala> FunctorFilter[List].collect(l){
* | case 1 => "one"
@@ -53,7 +71,7 @@ trait FunctorFilter[F[_]] extends Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val l: List[Option[Int]] = List(Some(1), None, Some(3), None)
* scala> l.flattenOption
* res0: List[Int] = List(1, 3)
@@ -91,10 +109,6 @@ object FunctorFilter extends ScalaVersionSpecificTraverseFilterInstances with Fu
implicit def catsTraverseFilterForQueue: TraverseFilter[Queue] =
cats.instances.queue.catsStdTraverseFilterForQueue
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[FunctorFilter]] for `F`.
*/
@@ -136,10 +150,6 @@ object FunctorFilter extends ScalaVersionSpecificTraverseFilterInstances with Fu
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToFunctorFilterOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
trait FunctorFilterInstances0 {
diff --git a/core/src/main/scala/cats/Inject.scala b/core/src/main/scala/cats/Inject.scala
index 3433246451..54b9b27896 100644
--- a/core/src/main/scala/cats/Inject.scala
+++ b/core/src/main/scala/cats/Inject.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
/**
@@ -30,19 +51,19 @@ sealed abstract private[cats] class InjectInstances {
new Inject[A, A] {
val inj = identity(_: A)
- val prj = Some(_: A)
+ val prj: A => Option[A] = Some(_: A)
}
implicit def catsLeftInjectInstance[A, B]: Inject[A, Either[A, B]] =
new Inject[A, Either[A, B]] {
- val inj = Left(_: A)
+ val inj: A => Either[A, B] = Left(_: A)
val prj = (_: Either[A, B]).left.toOption
}
implicit def catsRightInjectInstance[A, B, C](implicit I: Inject[A, B]): Inject[A, Either[C, B]] =
new Inject[A, Either[C, B]] {
- val inj = (a: A) => Right(I.inj(a))
+ val inj: A => Either[C, B] = (a: A) => Right(I.inj(a))
val prj = (_: Either[C, B]).toOption.flatMap(I.prj)
}
diff --git a/core/src/main/scala/cats/InjectK.scala b/core/src/main/scala/cats/InjectK.scala
index 73c2bcba6d..71f7a016a5 100644
--- a/core/src/main/scala/cats/InjectK.scala
+++ b/core/src/main/scala/cats/InjectK.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.arrow.FunctionK
@@ -37,16 +58,21 @@ sealed abstract private[cats] class InjectKInstances {
new InjectK[F, F] {
val inj = FunctionK.id[F]
- val prj = new FunctionK[F, λ[α => Option[F[α]]]] { def apply[A](a: F[A]): Option[F[A]] = Some(a) }
+ val prj: FunctionK[F, λ[α => Option[F[α]]]] = new FunctionK[F, λ[α => Option[F[α]]]] {
+ def apply[A](a: F[A]): Option[F[A]] = Some(a)
+ }
}
implicit def catsLeftInjectKInstance[F[_], G[_]]: InjectK[F, EitherK[F, G, *]] =
new InjectK[F, EitherK[F, G, *]] {
- val inj = new FunctionK[F, EitherK[F, G, *]] { def apply[A](a: F[A]): EitherK[F, G, A] = EitherK.leftc(a) }
-
- val prj = new FunctionK[EitherK[F, G, *], λ[α => Option[F[α]]]] {
- def apply[A](a: EitherK[F, G, A]): Option[F[A]] = a.run.left.toOption
+ val inj: FunctionK[F, EitherK[F, G, *]] = new FunctionK[F, EitherK[F, G, *]] {
+ def apply[A](a: F[A]): EitherK[F, G, A] = EitherK.leftc(a)
}
+
+ val prj: FunctionK[EitherK[F, G, *], λ[α => Option[F[α]]]] =
+ new FunctionK[EitherK[F, G, *], λ[α => Option[F[α]]]] {
+ def apply[A](a: EitherK[F, G, A]): Option[F[A]] = a.run.left.toOption
+ }
}
implicit def catsRightInjectKInstance[F[_], G[_], H[_]](implicit I: InjectK[F, G]): InjectK[F, EitherK[H, G, *]] =
@@ -54,9 +80,10 @@ sealed abstract private[cats] class InjectKInstances {
val inj = new FunctionK[G, EitherK[H, G, *]] { def apply[A](a: G[A]): EitherK[H, G, A] = EitherK.rightc(a) }
.compose(I.inj)
- val prj = new FunctionK[EitherK[H, G, *], λ[α => Option[F[α]]]] {
- def apply[A](a: EitherK[H, G, A]): Option[F[A]] = a.run.toOption.flatMap(I.prj(_))
- }
+ val prj: FunctionK[EitherK[H, G, *], λ[α => Option[F[α]]]] =
+ new FunctionK[EitherK[H, G, *], λ[α => Option[F[α]]]] {
+ def apply[A](a: EitherK[H, G, A]): Option[F[A]] = a.run.toOption.flatMap(I.prj(_))
+ }
}
}
diff --git a/core/src/main/scala/cats/Invariant.scala b/core/src/main/scala/cats/Invariant.scala
index 0c3896bd56..ddc31ec266 100644
--- a/core/src/main/scala/cats/Invariant.scala
+++ b/core/src/main/scala/cats/Invariant.scala
@@ -1,10 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.arrow.Arrow
import cats.kernel._
-import simulacrum.typeclass
+
import cats.kernel.compat.scalaVersionSpecific._
-import scala.annotation.implicitNotFound
+import org.typelevel.scalaccompat.annotation.targetName3
import scala.collection.immutable.{Queue, Seq, SortedMap}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try
@@ -13,8 +34,7 @@ import scala.util.control.TailCalls.TailRec
/**
* Must obey the laws defined in cats.laws.InvariantLaws.
*/
-@implicitNotFound("Could not find an instance of Invariant for ${F}")
-@typeclass trait Invariant[F[_]] extends Serializable { self =>
+trait Invariant[F[_]] extends Serializable { self =>
/**
* Transform an `F[A]` into an `F[B]` by providing a transformation from `A`
@@ -22,7 +42,7 @@ import scala.util.control.TailCalls.TailRec
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import scala.concurrent.duration._
*
* scala> val durSemigroup: Semigroup[FiniteDuration] =
@@ -38,7 +58,7 @@ import scala.util.control.TailCalls.TailRec
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import scala.concurrent.duration._
*
* scala> val durSemigroupList: Semigroup[List[FiniteDuration]] =
@@ -59,7 +79,7 @@ import scala.util.control.TailCalls.TailRec
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import scala.concurrent.duration._
*
* scala> val durSemigroupList: Semigroup[List[FiniteDuration]] =
@@ -82,7 +102,7 @@ import scala.util.control.TailCalls.TailRec
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import scala.concurrent.duration._
*
* scala> type ToInt[T] = T => Int
@@ -104,19 +124,22 @@ import scala.util.control.TailCalls.TailRec
@suppressUnusedImportWarningForScalaVersionSpecific
object Invariant extends ScalaVersionSpecificInvariantInstances with InvariantInstances0 {
- implicit def catsInstancesForId
- : Distributive[Id] with Bimonad[Id] with CommutativeMonad[Id] with NonEmptyTraverse[Id] =
+ implicit def catsInstancesForId: Distributive[Id] & Bimonad[Id] & CommutativeMonad[Id] & NonEmptyTraverse[Id] =
+ cats.catsInstancesForId
+ @deprecated("Added for bincompat", "2.8.0")
+ @targetName3("catsInstancesForId")
+ private[cats] def catsInstancesForIdCompat2_6_1: Comonad[Id] =
cats.catsInstancesForId
implicit def catsMonadErrorForEither[A]: MonadError[Either[A, *], A] =
cats.instances.either.catsStdInstancesForEither[A]
implicit def catsInstancesForOption
- : MonadError[Option, Unit] with Alternative[Option] with CoflatMap[Option] with CommutativeMonad[Option] =
+ : MonadError[Option, Unit] & Alternative[Option] & CoflatMap[Option] & CommutativeMonad[Option] =
cats.instances.option.catsStdInstancesForOption
- implicit def catsInstancesForList: Monad[List] with Alternative[List] with CoflatMap[List] =
+ implicit def catsInstancesForList: Monad[List] & Alternative[List] & CoflatMap[List] =
cats.instances.list.catsStdInstancesForList
- implicit def catsInstancesForVector: Monad[Vector] with Alternative[Vector] with CoflatMap[Vector] =
+ implicit def catsInstancesForVector: Monad[Vector] & Alternative[Vector] & CoflatMap[Vector] =
cats.instances.vector.catsStdInstancesForVector
- implicit def catsInstancesForQueue: Monad[Queue] with Alternative[Queue] with CoflatMap[Queue] =
+ implicit def catsInstancesForQueue: Monad[Queue] & Alternative[Queue] & CoflatMap[Queue] =
cats.instances.queue.catsStdInstancesForQueue
implicit def catsMonadForTailRec: Monad[TailRec] = cats.instances.tailRec.catsInstancesForTailRec
@@ -128,11 +151,21 @@ object Invariant extends ScalaVersionSpecificInvariantInstances with InvariantIn
cats.instances.function.catsStdContravariantMonoidalForFunction1[R]
implicit def catsFunctorForPair: Functor[λ[P => (P, P)]] = cats.instances.tuple.catsDataFunctorForPair
- implicit def catsInstancesForTry: MonadThrow[Try] with CoflatMap[Try] =
+ implicit def catsInstancesForTry: MonadThrow[Try] & CoflatMap[Try] =
cats.instances.try_.catsStdInstancesForTry
+
+ /**
+ * @deprecated
+ * Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
+ * (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
+ * We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
+ * However, at this time there are no plans to remove these instances from Cats.
+ *
+ * @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
+ */
implicit def catsInstancesForFuture(implicit
ec: ExecutionContext
- ): MonadThrow[Future] with CoflatMap[Future] =
+ ): MonadThrow[Future] & CoflatMap[Future] =
cats.instances.future.catsStdInstancesForFuture(ec)
implicit def catsContravariantMonoidalForOrder: ContravariantMonoidal[Order] =
@@ -248,10 +281,6 @@ object Invariant extends ScalaVersionSpecificInvariantInstances with InvariantIn
@deprecated("Use catsStdInstancesForTuple2 in cats.instances.NTupleMonadInstances", "2.4.0")
def catsComonadForTuple2[A]: Comonad[(A, *)] = cats.instances.tuple.catsStdInstancesForTuple2[A]
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Invariant]] for `F`.
*/
@@ -288,10 +317,6 @@ object Invariant extends ScalaVersionSpecificInvariantInstances with InvariantIn
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToInvariantOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[cats] trait InvariantInstances0 extends InvariantInstances1 {
@@ -313,7 +338,7 @@ private trait InvariantInstances1 extends InvariantInstances2 {
private[cats] trait InvariantInstances2 extends cats.instances.NTupleMonadInstances with TupleInstances0 {
implicit def catsApplicativeForArrow[F[_, _], A](implicit F: Arrow[F]): Applicative[F[A, *]] =
new ArrowApplicative[F, A](F)
- implicit def catsInstancesForSeq: Monad[Seq] with Alternative[Seq] with CoflatMap[Seq] =
+ implicit def catsInstancesForSeq: Monad[Seq] & Alternative[Seq] & CoflatMap[Seq] =
cats.instances.seq.catsStdInstancesForSeq
}
diff --git a/core/src/main/scala/cats/InvariantMonoidal.scala b/core/src/main/scala/cats/InvariantMonoidal.scala
index cea25680d6..3af1f113ee 100644
--- a/core/src/main/scala/cats/InvariantMonoidal.scala
+++ b/core/src/main/scala/cats/InvariantMonoidal.scala
@@ -1,22 +1,39 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* Invariant version of a Monoidal.
*
* Must obey the laws defined in cats.laws.InvariantMonoidalLaws.
*/
-@implicitNotFound("Could not find an instance of InvariantMonoidal for ${F}")
-@typeclass trait InvariantMonoidal[F[_]] extends InvariantSemigroupal[F] {
+trait InvariantMonoidal[F[_]] extends InvariantSemigroupal[F] {
/**
* `point` lifts any value into a Monoidal Functor.
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> InvariantMonoidal[Option].point(10)
* res0: Option[Int] = Some(10)
@@ -36,10 +53,6 @@ object InvariantMonoidal {
def monoid[F[_], A](implicit F: InvariantMonoidal[F], A: Monoid[A]): Monoid[F[A]] =
new InvariantMonoidalMonoid[F, A](F, A)
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[InvariantMonoidal]] for `F`.
*/
@@ -77,10 +90,6 @@ object InvariantMonoidal {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToInvariantMonoidalOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[cats] class InvariantMonoidalMonoid[F[_], A](f: InvariantMonoidal[F], monoid: Monoid[A])
diff --git a/core/src/main/scala/cats/InvariantSemigroupal.scala b/core/src/main/scala/cats/InvariantSemigroupal.scala
index 5e1fad14e9..dc504363d3 100644
--- a/core/src/main/scala/cats/InvariantSemigroupal.scala
+++ b/core/src/main/scala/cats/InvariantSemigroupal.scala
@@ -1,14 +1,31 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* [[InvariantSemigroupal]] is nothing more than something both invariant
* and Semigroupal. It comes up enough to be useful, and composes well
*/
-@implicitNotFound("Could not find an instance of InvariantSemigroupal for ${F}")
-@typeclass trait InvariantSemigroupal[F[_]] extends Semigroupal[F] with Invariant[F] { self =>
+trait InvariantSemigroupal[F[_]] extends Semigroupal[F] with Invariant[F] { self =>
def composeApply[G[_]: Apply]: InvariantSemigroupal[λ[α => F[G[α]]]] =
new ComposedInvariantApplySemigroupal[F, G] {
@@ -26,10 +43,6 @@ object InvariantSemigroupal extends SemigroupalArityFunctions {
def semigroup[F[_], A](implicit F: InvariantSemigroupal[F], A: Semigroup[A]): Semigroup[F[A]] =
new InvariantSemigroupalSemigroup[F, A](F, A)
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[InvariantSemigroupal]] for `F`.
*/
@@ -69,10 +82,6 @@ object InvariantSemigroupal extends SemigroupalArityFunctions {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToInvariantSemigroupalOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
private[cats] class InvariantSemigroupalSemigroup[F[_], A](f: InvariantSemigroupal[F], sg: Semigroup[A])
diff --git a/core/src/main/scala/cats/Monad.scala b/core/src/main/scala/cats/Monad.scala
index f52314384a..c694f854e3 100644
--- a/core/src/main/scala/cats/Monad.scala
+++ b/core/src/main/scala/cats/Monad.scala
@@ -1,7 +1,25 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.{noop, typeclass}
-import scala.annotation.implicitNotFound
+package cats
/**
* Monad.
@@ -12,8 +30,7 @@ import scala.annotation.implicitNotFound
*
* Must obey the laws defined in cats.laws.MonadLaws.
*/
-@implicitNotFound("Could not find an instance of Monad for ${F}")
-@typeclass trait Monad[F[_]] extends FlatMap[F] with Applicative[F] {
+trait Monad[F[_]] extends FlatMap[F] with Applicative[F] {
override def map[A, B](fa: F[A])(f: A => B): F[B] =
flatMap(fa)(a => pure(f(a)))
@@ -24,7 +41,7 @@ import scala.annotation.implicitNotFound
* This implementation uses append on each evaluation result,
* so avoid data structures with non-constant append performance, e.g. `List`.
*/
- @noop
+
def whileM[G[_], A](p: F[Boolean])(body: => F[A])(implicit G: Alternative[G]): F[G[A]] = {
val b = Eval.later(body)
tailRecM[G[A], G[A]](G.empty)(xs =>
@@ -44,7 +61,7 @@ import scala.annotation.implicitNotFound
* returns `true`. The condition is evaluated before the loop body.
* Discards results.
*/
- @noop
+
def whileM_[A](p: F[Boolean])(body: => F[A]): F[Unit] = {
val continue: Either[Unit, Unit] = Left(())
val stop: F[Either[Unit, Unit]] = pure(Right(()))
@@ -130,7 +147,7 @@ import scala.annotation.implicitNotFound
* [[https://github.com/typelevel/cats/pull/3553#discussion_r468121480 implementation]] due to P. Oscar Boykin
* @see See [[https://gitter.im/typelevel/cats-effect?at=5f297e4314c413356f56d230]] for the discussion.
*/
- @noop
+
def ifElseM[A](branches: (F[Boolean], F[A])*)(els: F[A]): F[A] = {
type Branches = List[(F[Boolean], F[A])]
@@ -144,14 +161,24 @@ import scala.annotation.implicitNotFound
tailRecM(branches.toList)(step)
}
+
+ /**
+ * Modifies the `A` value in `F[A]` with the supplied function, if the function is defined for the value.
+ * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ *
+ * scala> List(1, 2, 3).flatMapOrKeep{ case 2 => List(2, 22, 222) }
+ * res0: List[Int] = List(1, 2, 22, 222, 3)
+ * }}}
+ */
+ def flatMapOrKeep[A, A1 >: A](fa: F[A])(pfa: PartialFunction[A, F[A1]]): F[A1] =
+ flatMap(fa)(a => pfa.applyOrElse(a, pure[A1]))
+
}
object Monad {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Monad]] for `F`.
*/
@@ -194,8 +221,4 @@ object Monad {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToMonadOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/MonadError.scala b/core/src/main/scala/cats/MonadError.scala
index 97e8264250..c6e1bfa136 100644
--- a/core/src/main/scala/cats/MonadError.scala
+++ b/core/src/main/scala/cats/MonadError.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
/**
@@ -24,7 +45,7 @@ trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F] {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import scala.util.{Try, Success}
*
* scala> val a: Try[Either[Throwable, Int]] = Success(Left(new java.lang.Exception))
@@ -87,7 +108,7 @@ trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F] {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import scala.util.{Try, Success, Failure}
*
* scala> def checkError(result: Either[Throwable, Int]): Try[String] = result.fold(_ => Failure(new java.lang.Exception), _ => Success("success"))
diff --git a/core/src/main/scala/cats/MonoidK.scala b/core/src/main/scala/cats/MonoidK.scala
index c09eda910a..38a1191791 100644
--- a/core/src/main/scala/cats/MonoidK.scala
+++ b/core/src/main/scala/cats/MonoidK.scala
@@ -1,7 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+import cats.kernel.compat.scalaVersionSpecific._
/**
* MonoidK is a universal monoid which operates on kinds.
@@ -23,27 +43,41 @@ import scala.annotation.implicitNotFound
* combination operation and empty value just depend on the
* structure of F, but not on the structure of A.
*/
-@implicitNotFound("Could not find an instance of MonoidK for ${F}")
-@typeclass trait MonoidK[F[_]] extends SemigroupK[F] { self =>
+trait MonoidK[F[_]] extends SemigroupK[F] { self =>
/**
* Given a type A, create an "empty" F[A] value.
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> MonoidK[List].empty[Long]
* res0: List[Long] = List()
* }}}
*/
def empty[A]: F[A]
+ /**
+ * Tests if `a` is the identity.
+ *
+ * Example:
+ * {{{
+ * scala> MonoidK[List].isEmpty(List.empty[String])
+ * res0: Boolean = true
+ *
+ * scala> MonoidK[List].isEmpty(List("something"))
+ * res1: Boolean = false
+ * }}}
+ */
+ def isEmpty[A](a: F[A])(implicit ev: Eq[F[A]]): Boolean =
+ ev.eqv(a, empty)
+
/**
* Given a type A, create a concrete Monoid[F[A]].
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> MonoidK[List].algebra[Long].empty
* res0: List[Long] = List()
* }}}
@@ -59,7 +93,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val monoidK = MonoidK[List].compose[Option]
* scala> monoidK.combineK(List(Some(1)), List(Some(2), None))
* res0: List[Option[Int]] = List(Some(1), Some(2), None)
@@ -69,14 +103,56 @@ import scala.annotation.implicitNotFound
new ComposedMonoidK[F, G] {
val F: MonoidK[F] = self
}
+
+ /**
+ * Return `a` combined with itself `n` times.
+ *
+ * Example:
+ * {{{
+ * scala> SemigroupK[List].combineNK(List(1), 5)
+ * res0: List[Int] = List(1, 1, 1, 1, 1)
+
+ * scala> MonoidK[List].combineNK(List("ha"), 0)
+ * res1: List[String] = List()
+ *
+ * }}}
+ */
+ override def combineNK[A](a: F[A], n: Int): F[A] =
+ if (n < 0) throw new IllegalArgumentException("Repeated combining for monoidKs must have n >= 0")
+ else if (n == 0) empty[A]
+ else repeatedCombineNK(a, n)
+
+ /**
+ * Given a sequence of `as`, sum them using the monoidK and return the total.
+ *
+ * Example:
+ * {{{
+ * scala> MonoidK[List].combineAllK(List(List("One"), List("Two"), List("Three")))
+ * res0: List[String] = List(One, Two, Three)
+ *
+ * scala> MonoidK[List].combineAllK[String](List.empty)
+ * res1: List[String] = List()
+ * }}}
+ */
+ def combineAllK[A](as: IterableOnce[F[A]]): F[A] =
+ combineAllOptionK(as) match {
+ case Some(fa) => fa
+ case None => empty[A]
+ }
+
+ override def reverse: MonoidK[F] =
+ new MonoidK[F] {
+ def empty[A] = self.empty
+ def combineK[A](a: F[A], b: F[A]) = self.combineK(b, a)
+ // a + a + a + ... is the same when reversed
+ override def combineNK[A](a: F[A], n: Int): F[A] = self.combineNK(a, n)
+ override def reverse = self
+ }
}
+@suppressUnusedImportWarningForScalaVersionSpecific
object MonoidK {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[MonoidK]] for `F`.
*/
@@ -114,8 +190,4 @@ object MonoidK {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToMonoidKOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/NonEmptyAlternative.scala b/core/src/main/scala/cats/NonEmptyAlternative.scala
index 60caebf67a..a5d846c30f 100644
--- a/core/src/main/scala/cats/NonEmptyAlternative.scala
+++ b/core/src/main/scala/cats/NonEmptyAlternative.scala
@@ -1,10 +1,27 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
-@implicitNotFound("Could not find an instance of NonEmptyAlternative for ${F}")
-@typeclass trait NonEmptyAlternative[F[_]] extends Applicative[F] with SemigroupK[F] { self =>
+trait NonEmptyAlternative[F[_]] extends Applicative[F] with SemigroupK[F] { self =>
/**
* Lift `a` into `F[_]` and prepend it to `fa`.
@@ -36,9 +53,6 @@ import scala.annotation.implicitNotFound
}
object NonEmptyAlternative {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
/**
* Summon an instance of [[NonEmptyAlternative]] for `F`.
@@ -59,8 +73,7 @@ object NonEmptyAlternative {
type TypeClassType <: NonEmptyAlternative[F]
def self: F[A]
val typeClassInstance: TypeClassType
- // Note: `prependK` has to be added manually since simulacrum is not able to handle `self` as a second parameter.
- // def prependK(a: A): F[A] = typeClassInstance.prependK[A](a, self)
+ def prependK(a: A): F[A] = typeClassInstance.prependK[A](a, self)
def appendK(a: A): F[A] = typeClassInstance.appendK[A](self, a)
}
trait AllOps[F[_], A] extends Ops[F, A] with Applicative.AllOps[F, A] with SemigroupK.AllOps[F, A] {
@@ -78,7 +91,4 @@ object NonEmptyAlternative {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToNonEmptyAlternativeOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
}
diff --git a/core/src/main/scala/cats/NonEmptyReducible.scala b/core/src/main/scala/cats/NonEmptyReducible.scala
new file mode 100644
index 0000000000..82e5e1ae48
--- /dev/null
+++ b/core/src/main/scala/cats/NonEmptyReducible.scala
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats
+
+import cats.Foldable.Source
+import cats.data.NonEmptyList
+
+/**
+ * This class defines a `Reducible[F]` in terms of a `Foldable[G]`
+ * together with a `split` method, `F[A]` => `(A, G[A])`.
+ *
+ * This class can be used on any type where the first value (`A`) and
+ * the "rest" of the values (`G[A]`) can be easily found.
+ *
+ * This class is only a helper, does not define a typeclass and should not be used outside of Cats.
+ * Also see the discussion: PR #3541 and issue #3069.
+ */
+abstract class NonEmptyReducible[F[_], G[_]](implicit G: Foldable[G]) extends Reducible[F] {
+ def split[A](fa: F[A]): (A, G[A])
+
+ def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B = {
+ val (a, ga) = split(fa)
+ G.foldLeft(ga, f(b, a))(f)
+ }
+
+ def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
+ Always(split(fa)).flatMap { case (a, ga) =>
+ f(a, G.foldRight(ga, lb)(f))
+ }
+
+ def reduceLeftTo[A, B](fa: F[A])(f: A => B)(g: (B, A) => B): B = {
+ val (a, ga) = split(fa)
+ G.foldLeft(ga, f(a))((b, a) => g(b, a))
+ }
+
+ def reduceRightTo[A, B](fa: F[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] = {
+ def loop(now: A, source: Source[A]): Eval[B] =
+ source.uncons match {
+ case Some((next, s)) => g(now, Eval.defer(loop(next, s.value)))
+ case None => Eval.later(f(now))
+ }
+
+ Always(split(fa)).flatMap { case (a, ga) =>
+ Eval.defer(loop(a, Foldable.Source.fromFoldable(ga)))
+ }
+ }
+
+ override def size[A](fa: F[A]): Long = {
+ val (_, tail) = split(fa)
+ 1 + G.size(tail)
+ }
+
+ override def get[A](fa: F[A])(idx: Long): Option[A] =
+ if (idx == 0L) Some(split(fa)._1) else G.get(split(fa)._2)(idx - 1L)
+
+ override def fold[A](fa: F[A])(implicit A: Monoid[A]): A = {
+ val (a, ga) = split(fa)
+ A.combine(a, G.fold(ga))
+ }
+
+ override def foldM[H[_], A, B](fa: F[A], z: B)(f: (B, A) => H[B])(implicit H: Monad[H]): H[B] = {
+ val (a, ga) = split(fa)
+ H.flatMap(f(z, a))(G.foldM(ga, _)(f))
+ }
+
+ override def find[A](fa: F[A])(f: A => Boolean): Option[A] = {
+ val (a, ga) = split(fa)
+ if (f(a)) Some(a) else G.find(ga)(f)
+ }
+
+ override def exists[A](fa: F[A])(p: A => Boolean): Boolean = {
+ val (a, ga) = split(fa)
+ p(a) || G.exists(ga)(p)
+ }
+
+ override def forall[A](fa: F[A])(p: A => Boolean): Boolean = {
+ val (a, ga) = split(fa)
+ p(a) && G.forall(ga)(p)
+ }
+
+ override def toList[A](fa: F[A]): List[A] = {
+ val (a, ga) = split(fa)
+ a :: G.toList(ga)
+ }
+
+ override def toNonEmptyList[A](fa: F[A]): NonEmptyList[A] = {
+ val (a, ga) = split(fa)
+ NonEmptyList(a, G.toList(ga))
+ }
+
+ override def filter_[A](fa: F[A])(p: A => Boolean): List[A] = {
+ val (a, ga) = split(fa)
+ val filteredTail = G.filter_(ga)(p)
+ if (p(a)) a :: filteredTail else filteredTail
+ }
+
+ override def takeWhile_[A](fa: F[A])(p: A => Boolean): List[A] = {
+ val (a, ga) = split(fa)
+ if (p(a)) a :: G.takeWhile_(ga)(p) else Nil
+ }
+
+ override def dropWhile_[A](fa: F[A])(p: A => Boolean): List[A] = {
+ val (a, ga) = split(fa)
+ if (p(a)) G.dropWhile_(ga)(p) else a :: G.toList(ga)
+ }
+}
diff --git a/core/src/main/scala/cats/NonEmptyTraverse.scala b/core/src/main/scala/cats/NonEmptyTraverse.scala
index 7a87167b48..fe0beea466 100644
--- a/core/src/main/scala/cats/NonEmptyTraverse.scala
+++ b/core/src/main/scala/cats/NonEmptyTraverse.scala
@@ -1,7 +1,25 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* NonEmptyTraverse, also known as Traversable1.
@@ -9,8 +27,7 @@ import scala.annotation.implicitNotFound
* `NonEmptyTraverse` is like a non-empty `Traverse`. In addition to the traverse and sequence
* methods it provides nonEmptyTraverse and nonEmptySequence methods which require an `Apply` instance instead of `Applicative`.
*/
-@implicitNotFound("Could not find an instance of NonEmptyTraverse for ${F}")
-@typeclass trait NonEmptyTraverse[F[_]] extends Traverse[F] with Reducible[F] { self =>
+trait NonEmptyTraverse[F[_]] extends Traverse[F] with Reducible[F] { self =>
/**
* Given a function which returns a G effect, thread this effect
@@ -19,7 +36,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.NonEmptyList
* scala> def countWords(words: List[String]): Map[String, Int] = words.groupBy(identity).map { case (k, v) => (k, v.length) }
* scala> val expectedResult = Map("do" -> NonEmptyList.of(1, 2), "you" -> NonEmptyList.of(1, 1))
@@ -38,7 +55,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.NonEmptyList
* scala> val x = NonEmptyList.of(Map("do" -> 1, "you" -> 1), Map("do" -> 2, "you" -> 1))
* scala> val y = NonEmptyList.of(Map("How" -> 3, "do" -> 1, "you" -> 1), Map[String,Int]())
@@ -56,7 +73,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.NonEmptyList
* scala> val x = NonEmptyList.of(List("How", "do", "you", "fly"), List("What", "do", "you", "do"))
* scala> x.nonEmptyFlatTraverse(_.groupByNel(identity) : Map[String, NonEmptyList[String]])
@@ -72,7 +89,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.NonEmptyList
* scala> val x = NonEmptyList.of(Map(0 ->NonEmptyList.of(1, 2)), Map(0 -> NonEmptyList.of(3)))
* scala> val y: NonEmptyList[Map[Int, NonEmptyList[Int]]] = NonEmptyList.of(Map(), Map(1 -> NonEmptyList.of(3)))
@@ -98,10 +115,6 @@ import scala.annotation.implicitNotFound
object NonEmptyTraverse {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[NonEmptyTraverse]] for `F`.
*/
@@ -147,8 +160,4 @@ object NonEmptyTraverse {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToNonEmptyTraverseOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/NotNull.scala b/core/src/main/scala/cats/NotNull.scala
index ec0e308a63..137eaff008 100644
--- a/core/src/main/scala/cats/NotNull.scala
+++ b/core/src/main/scala/cats/NotNull.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
/**
diff --git a/core/src/main/scala/cats/Parallel.scala b/core/src/main/scala/cats/Parallel.scala
index 7f8ab11ec5..9b19eda831 100644
--- a/core/src/main/scala/cats/Parallel.scala
+++ b/core/src/main/scala/cats/Parallel.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.arrow.FunctionK
@@ -136,7 +157,7 @@ object Parallel extends ParallelArityFunctions2 {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data._
* scala> val list: List[Int] = List(1, 2, 3, 4)
* scala> def validate(n: Int): EitherNec[String, Option[Int]] =
@@ -161,7 +182,7 @@ object Parallel extends ParallelArityFunctions2 {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data._
* scala> val list: List[EitherNec[String, Option[Int]]] = List(Left(NonEmptyChain.one("Error")), Left(NonEmptyChain.one("Warning!")))
* scala> list.parSequenceFilter
@@ -180,7 +201,7 @@ object Parallel extends ParallelArityFunctions2 {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data._
* scala> val list: List[Int] = List(1, 2, 3, 4)
* scala> def validate(n: Int): EitherNec[String, Boolean] =
@@ -239,25 +260,39 @@ object Parallel extends ParallelArityFunctions2 {
}
/**
- * Like `Foldable[A].sequence_`, but uses the applicative instance
+ * Like `Foldable[A].sequenceVoid`, but uses the applicative instance
* corresponding to the Parallel instance instead.
*/
- def parSequence_[T[_]: Foldable, M[_], A](tma: T[M[A]])(implicit P: Parallel[M]): M[Unit] = {
- val fu: P.F[Unit] = Foldable[T].traverse_(tma)(P.parallel.apply(_))(P.applicative)
+ def parSequenceVoid[T[_]: Foldable, M[_], A](tma: T[M[A]])(implicit P: Parallel[M]): M[Unit] = {
+ val fu: P.F[Unit] = Foldable[T].traverseVoid(tma)(P.parallel.apply(_))(P.applicative)
P.sequential(fu)
}
/**
- * Like `Foldable[A].traverse_`, but uses the applicative instance
+ * Alias for `parSequenceVoid`.
+ *
+ * @deprecated this method should be considered as deprecated and replaced by `parSequenceVoid`.
+ */
+ def parSequence_[T[_]: Foldable, M[_], A](tma: T[M[A]])(implicit P: Parallel[M]): M[Unit] =
+ parSequenceVoid(tma)
+
+ /**
+ * Like `Foldable[A].traverseVoid`, but uses the applicative instance
* corresponding to the Parallel instance instead.
*/
- def parTraverse_[T[_]: Foldable, M[_], A, B](
- ta: T[A]
- )(f: A => M[B])(implicit P: Parallel[M]): M[Unit] = {
- val gtb: P.F[Unit] = Foldable[T].traverse_(ta)(a => P.parallel(f(a)))(P.applicative)
+ def parTraverseVoid[T[_]: Foldable, M[_], A, B](ta: T[A])(f: A => M[B])(implicit P: Parallel[M]): M[Unit] = {
+ val gtb: P.F[Unit] = Foldable[T].traverseVoid(ta)(a => P.parallel(f(a)))(P.applicative)
P.sequential(gtb)
}
+ /**
+ * Alias for `parTraverseVoid`.
+ *
+ * @deprecated this method should be considered as deprecated and replaced by `parTraverseVoid`.
+ */
+ def parTraverse_[T[_]: Foldable, M[_], A, B](ta: T[A])(f: A => M[B])(implicit P: Parallel[M]): M[Unit] =
+ parTraverseVoid(ta)(f)
+
def parUnorderedTraverse[T[_]: UnorderedTraverse, M[_], F[_]: CommutativeApplicative, A, B](
ta: T[A]
)(f: A => M[B])(implicit P: Parallel.Aux[M, F]): M[T[B]] =
@@ -324,27 +359,47 @@ object Parallel extends ParallelArityFunctions2 {
}
/**
- * Like `Reducible[A].nonEmptySequence_`, but uses the apply instance
+ * Like `Reducible[A].nonEmptySequenceVoid`, but uses the apply instance
* corresponding to the Parallel instance instead.
*/
- def parNonEmptySequence_[T[_]: Reducible, M[_], A](
+ def parNonEmptySequenceVoid[T[_]: Reducible, M[_], A](
tma: T[M[A]]
)(implicit P: NonEmptyParallel[M]): M[Unit] = {
- val fu: P.F[Unit] = Reducible[T].nonEmptyTraverse_(tma)(P.parallel.apply(_))(P.apply)
+ val fu: P.F[Unit] = Reducible[T].nonEmptyTraverseVoid(tma)(P.parallel.apply(_))(P.apply)
P.sequential(fu)
}
/**
- * Like `Reducible[A].nonEmptyTraverse_`, but uses the apply instance
+ * Alias for `parNonEmptySequenceVoid`.
+ *
+ * @deprecated this method should be considered as deprecated and replaced by `parNonEmptySequenceVoid`.
+ */
+ def parNonEmptySequence_[T[_]: Reducible, M[_], A](
+ tma: T[M[A]]
+ )(implicit P: NonEmptyParallel[M]): M[Unit] =
+ parNonEmptySequenceVoid[T, M, A](tma)
+
+ /**
+ * Like `Reducible[A].nonEmptyTraverseVoid`, but uses the apply instance
* corresponding to the Parallel instance instead.
*/
- def parNonEmptyTraverse_[T[_]: Reducible, M[_], A, B](
+ def parNonEmptyTraverseVoid[T[_]: Reducible, M[_], A, B](
ta: T[A]
)(f: A => M[B])(implicit P: NonEmptyParallel[M]): M[Unit] = {
- val gtb: P.F[Unit] = Reducible[T].nonEmptyTraverse_(ta)(a => P.parallel(f(a)))(P.apply)
+ val gtb: P.F[Unit] = Reducible[T].nonEmptyTraverseVoid(ta)(a => P.parallel(f(a)))(P.apply)
P.sequential(gtb)
}
+ /**
+ * Alias for `parNonEmptyTraverseVoid`.
+ *
+ * @deprecated this method should be considered as deprecated and replaced by `parNonEmptyTraverseVoid`.
+ */
+ def parNonEmptyTraverse_[T[_]: Reducible, M[_], A, B](
+ ta: T[A]
+ )(f: A => M[B])(implicit P: NonEmptyParallel[M]): M[Unit] =
+ parNonEmptyTraverseVoid[T, M, A, B](ta)(f)
+
/**
* Like `Bitraverse[A].bitraverse`, but uses the applicative instance
* corresponding to the Parallel instance instead.
@@ -445,6 +500,13 @@ object Parallel extends ParallelArityFunctions2 {
def parReplicateA[M[_], A](n: Int, ma: M[A])(implicit P: Parallel[M]): M[List[A]] =
P.sequential(P.applicative.replicateA(n, P.parallel(ma)))
+ /**
+ * Like `Applicative[F].replicateA_`, but uses the apply instance
+ * corresponding to the Parallel instance instead.
+ */
+ def parReplicateA_[M[_], A](n: Int, ma: M[A])(implicit P: Parallel[M]): M[Unit] =
+ P.sequential(P.applicative.replicateA_(n, P.parallel(ma)))
+
/**
* Provides an `ApplicativeError[F, E]` instance for any F, that has a `Parallel.Aux[M, F]`
* and a `MonadError[M, E]` instance.
diff --git a/core/src/main/scala/cats/Reducible.scala b/core/src/main/scala/cats/Reducible.scala
index ff0a114376..a51ba629b2 100644
--- a/core/src/main/scala/cats/Reducible.scala
+++ b/core/src/main/scala/cats/Reducible.scala
@@ -1,9 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
-import cats.Foldable.Source
import cats.data.{Ior, NonEmptyList}
-import simulacrum.{noop, typeclass}
-import scala.annotation.implicitNotFound
/**
* Data structures that can be reduced to a summary value.
@@ -18,8 +36,7 @@ import scala.annotation.implicitNotFound
* - `reduceLeftTo(fa)(f)(g)` eagerly reduces with an additional mapping function
* - `reduceRightTo(fa)(f)(g)` lazily reduces with an additional mapping function
*/
-@implicitNotFound("Could not find an instance of Reducible for ${F}")
-@typeclass trait Reducible[F[_]] extends Foldable[F] { self =>
+trait Reducible[F[_]] extends Foldable[F] { self =>
/**
* Left-associative reduction on `F` using the function `f`.
@@ -46,6 +63,13 @@ import scala.annotation.implicitNotFound
* semigroup for `G[_]`.
*
* This method is a generalization of `reduce`.
+ *
+ * {{{
+ * scala> import cats.Reducible
+ * scala> import cats.data._
+ * scala> Reducible[NonEmptyVector].reduceK(NonEmptyVector.of(NonEmptyList.of(1, 2, 3), NonEmptyList.of(4, 5, 6), NonEmptyList.of(7, 8, 9)))
+ * res0: NonEmptyList[Int] = NonEmptyList(1, 2, 3, 4, 5, 6, 7, 8, 9)
+ * }}}
*/
def reduceK[G[_], A](fga: F[G[A]])(implicit G: SemigroupK[G]): G[A] =
reduce(fga)(G.algebra)
@@ -53,6 +77,17 @@ import scala.annotation.implicitNotFound
/**
* Apply `f` to each element of `fa` and combine them using the
* given `Semigroup[B]`.
+ *
+ * {{{
+ * scala> import cats.Reducible
+ * scala> import cats.data.NonEmptyList
+ * scala> Reducible[NonEmptyList].reduceMap(NonEmptyList.of(1, 2, 3))(v => v.toString * v)
+ * res0: String = 122333
+ *
+ * scala> val gt5: Int => Option[Int] = (num: Int) => Some(num).filter(_ > 5)
+ * scala> Reducible[NonEmptyList].reduceMap(NonEmptyList.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))(gt5)
+ * res1: Option[Int] = Some(40)
+ * }}}
*/
def reduceMap[A, B](fa: F[A])(f: A => B)(implicit B: Semigroup[B]): B =
reduceLeftTo(fa)(f)((b, a) => B.combine(b, f(a)))
@@ -62,14 +97,14 @@ import scala.annotation.implicitNotFound
* given `SemigroupK[G]`.
*
* {{{
- * scala> import cats._, cats.data._, cats.implicits._
+ * scala> import cats._, cats.data._
* scala> val f: Int => Endo[String] = i => (s => s + i)
* scala> val x: Endo[String] = Reducible[NonEmptyList].reduceMapK(NonEmptyList.of(1, 2, 3))(f)
* scala> val a = x("foo")
* a: String = "foo321"
* }}}
*/
- @noop
+
def reduceMapK[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: SemigroupK[G]): G[B] =
reduceLeftTo(fa)(f)((b, a) => G.combineK(b, f(a)))
@@ -90,10 +125,8 @@ import scala.annotation.implicitNotFound
* semigroup for `G[_]`.
*
* This method is similar to [[reduce]], but may short-circuit.
- *
- * See [[https://github.com/typelevel/simulacrum/issues/162 this issue]] for an explanation of `@noop` usage.
*/
- @noop def reduceA[G[_], A](fga: F[G[A]])(implicit G: Apply[G], A: Semigroup[A]): G[A] =
+ def reduceA[G[_], A](fga: F[G[A]])(implicit G: Apply[G], A: Semigroup[A]): G[A] =
reduceMapA(fga)(identity)
/**
@@ -105,7 +138,6 @@ import scala.annotation.implicitNotFound
* {{{
* scala> import cats.Reducible
* scala> import cats.data.NonEmptyList
- * scala> import cats.implicits._
* scala> val evenOpt: Int => Option[Int] =
* | i => if (i % 2 == 0) Some(i) else None
* scala> val allEven = NonEmptyList.of(2,4,6,8,10)
@@ -130,7 +162,6 @@ import scala.annotation.implicitNotFound
* {{{
* scala> import cats.Reducible
* scala> import cats.data.NonEmptyList
- * scala> import cats.implicits._
* scala> val evenOpt: Int => Option[Int] =
* | i => if (i % 2 == 0) Some(i) else None
* scala> val allEven = NonEmptyList.of(2,4,6,8,10)
@@ -170,31 +201,47 @@ import scala.annotation.implicitNotFound
* `A` values will be mapped into `G[B]` and combined using
* `Apply#map2`.
*
- * This method is similar to [[Foldable.traverse_]]. There are two
+ * This method is similar to [[Foldable.traverseVoid]]. There are two
* main differences:
*
* 1. We only need an [[Apply]] instance for `G` here, since we
* don't need to call [[Applicative.pure]] for a starting value.
* 2. This performs a strict left-associative traversal and thus
* must always traverse the entire data structure. Prefer
- * [[Foldable.traverse_]] if you have an [[Applicative]] instance
+ * [[Foldable.traverseVoid]] if you have an [[Applicative]] instance
* available for `G` and want to take advantage of short-circuiting
* the traversal.
*/
- def nonEmptyTraverse_[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Apply[G]): G[Unit] = {
+ def nonEmptyTraverseVoid[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Apply[G]): G[Unit] = {
val f1 = f.andThen(G.void)
reduceRightTo(fa)(f1)((x, y) => G.map2Eval(f1(x), y)((_, b) => b)).value
}
+ /**
+ * Alias for `nonEmptyTraverseVoid`.
+ *
+ * @deprecated this method should be considered as deprecated and replaced by `nonEmptyTraverseVoid`.
+ */
+ def nonEmptyTraverse_[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Apply[G]): G[Unit] =
+ nonEmptyTraverseVoid(fa)(f)
+
/**
* Sequence `F[G[A]]` using `Apply[G]`.
*
- * This method is similar to [[Foldable.sequence_]] but requires only
+ * This method is similar to [[Foldable.sequenceVoid]] but requires only
* an [[Apply]] instance for `G` instead of [[Applicative]]. See the
- * [[nonEmptyTraverse_]] documentation for a description of the differences.
+ * [[nonEmptyTraverseVoid]] documentation for a description of the differences.
+ */
+ def nonEmptySequenceVoid[G[_], A](fga: F[G[A]])(implicit G: Apply[G]): G[Unit] =
+ nonEmptyTraverseVoid(fga)(identity)
+
+ /**
+ * Alias for `nonEmptySequenceVoid`.
+ *
+ * @deprecated this method should be considered as deprecated and replaced by `nonEmptySequenceVoid`.
*/
def nonEmptySequence_[G[_], A](fga: F[G[A]])(implicit G: Apply[G]): G[Unit] =
- nonEmptyTraverse_(fga)(identity)
+ nonEmptySequenceVoid(fga)
def toNonEmptyList[A](fa: F[A]): NonEmptyList[A] =
reduceRightTo(fa)(a => NonEmptyList(a, Nil)) { (a, lnel) =>
@@ -277,7 +324,6 @@ import scala.annotation.implicitNotFound
* Intercalate/insert an element between the existing elements while reducing.
*
* {{{
- * scala> import cats.implicits._
* scala> import cats.data.NonEmptyList
* scala> val nel = NonEmptyList.of("a", "b", "c")
* scala> Reducible[NonEmptyList].nonEmptyIntercalate(nel, "-")
@@ -333,10 +379,6 @@ import scala.annotation.implicitNotFound
object Reducible {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Reducible]] for `F`.
*/
@@ -372,10 +414,14 @@ object Reducible {
typeClassInstance.reduceMapM[G, A, B](self)(f)(G, B)
def reduceRightTo[B](f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] =
typeClassInstance.reduceRightTo[A, B](self)(f)(g)
+ def nonEmptyTraverseVoid[G[_], B](f: A => G[B])(implicit G: Apply[G]): G[Unit] =
+ typeClassInstance.nonEmptyTraverseVoid[G, A, B](self)(f)
def nonEmptyTraverse_[G[_], B](f: A => G[B])(implicit G: Apply[G]): G[Unit] =
- typeClassInstance.nonEmptyTraverse_[G, A, B](self)(f)(G)
+ nonEmptyTraverseVoid[G, B](f)
+ def nonEmptySequenceVoid[G[_], B](implicit ev$1: A <:< G[B], G: Apply[G]): G[Unit] =
+ typeClassInstance.nonEmptySequenceVoid[G, B](self.asInstanceOf[F[G[B]]])
def nonEmptySequence_[G[_], B](implicit ev$1: A <:< G[B], G: Apply[G]): G[Unit] =
- typeClassInstance.nonEmptySequence_[G, B](self.asInstanceOf[F[G[B]]])(G)
+ nonEmptySequenceVoid[G, B]
def toNonEmptyList: NonEmptyList[A] = typeClassInstance.toNonEmptyList[A](self)
def minimum(implicit A: Order[A]): A = typeClassInstance.minimum[A](self)(A)
def maximum(implicit A: Order[A]): A = typeClassInstance.maximum[A](self)(A)
@@ -407,108 +453,4 @@ object Reducible {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToReducibleOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
-}
-
-/**
- * This class defines a `Reducible[F]` in terms of a `Foldable[G]`
- * together with a `split` method, `F[A]` => `(A, G[A])`.
- *
- * This class can be used on any type where the first value (`A`) and
- * the "rest" of the values (`G[A]`) can be easily found.
- *
- * This class is only a helper, does not define a typeclass and should not be used outside of Cats.
- * Also see the discussion: PR #3541 and issue #3069.
- */
-abstract class NonEmptyReducible[F[_], G[_]](implicit G: Foldable[G]) extends Reducible[F] {
- def split[A](fa: F[A]): (A, G[A])
-
- def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B = {
- val (a, ga) = split(fa)
- G.foldLeft(ga, f(b, a))(f)
- }
-
- def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
- Always(split(fa)).flatMap { case (a, ga) =>
- f(a, G.foldRight(ga, lb)(f))
- }
-
- def reduceLeftTo[A, B](fa: F[A])(f: A => B)(g: (B, A) => B): B = {
- val (a, ga) = split(fa)
- G.foldLeft(ga, f(a))((b, a) => g(b, a))
- }
-
- def reduceRightTo[A, B](fa: F[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] = {
- def loop(now: A, source: Source[A]): Eval[B] =
- source.uncons match {
- case Some((next, s)) => g(now, Eval.defer(loop(next, s.value)))
- case None => Eval.later(f(now))
- }
-
- Always(split(fa)).flatMap { case (a, ga) =>
- Eval.defer(loop(a, Foldable.Source.fromFoldable(ga)))
- }
- }
-
- override def size[A](fa: F[A]): Long = {
- val (_, tail) = split(fa)
- 1 + G.size(tail)
- }
-
- override def get[A](fa: F[A])(idx: Long): Option[A] =
- if (idx == 0L) Some(split(fa)._1) else G.get(split(fa)._2)(idx - 1L)
-
- override def fold[A](fa: F[A])(implicit A: Monoid[A]): A = {
- val (a, ga) = split(fa)
- A.combine(a, G.fold(ga))
- }
-
- override def foldM[H[_], A, B](fa: F[A], z: B)(f: (B, A) => H[B])(implicit H: Monad[H]): H[B] = {
- val (a, ga) = split(fa)
- H.flatMap(f(z, a))(G.foldM(ga, _)(f))
- }
-
- override def find[A](fa: F[A])(f: A => Boolean): Option[A] = {
- val (a, ga) = split(fa)
- if (f(a)) Some(a) else G.find(ga)(f)
- }
-
- override def exists[A](fa: F[A])(p: A => Boolean): Boolean = {
- val (a, ga) = split(fa)
- p(a) || G.exists(ga)(p)
- }
-
- override def forall[A](fa: F[A])(p: A => Boolean): Boolean = {
- val (a, ga) = split(fa)
- p(a) && G.forall(ga)(p)
- }
-
- override def toList[A](fa: F[A]): List[A] = {
- val (a, ga) = split(fa)
- a :: G.toList(ga)
- }
-
- override def toNonEmptyList[A](fa: F[A]): NonEmptyList[A] = {
- val (a, ga) = split(fa)
- NonEmptyList(a, G.toList(ga))
- }
-
- override def filter_[A](fa: F[A])(p: A => Boolean): List[A] = {
- val (a, ga) = split(fa)
- val filteredTail = G.filter_(ga)(p)
- if (p(a)) a :: filteredTail else filteredTail
- }
-
- override def takeWhile_[A](fa: F[A])(p: A => Boolean): List[A] = {
- val (a, ga) = split(fa)
- if (p(a)) a :: G.takeWhile_(ga)(p) else Nil
- }
-
- override def dropWhile_[A](fa: F[A])(p: A => Boolean): List[A] = {
- val (a, ga) = split(fa)
- if (p(a)) G.dropWhile_(ga)(p) else a :: G.toList(ga)
- }
}
diff --git a/core/src/main/scala/cats/Representable.scala b/core/src/main/scala/cats/Representable.scala
index 7f3460c6ad..5316884b4f 100644
--- a/core/src/main/scala/cats/Representable.scala
+++ b/core/src/main/scala/cats/Representable.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
/**
@@ -24,7 +45,7 @@ trait Representable[F[_]] extends Serializable { self =>
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> type Pair[A] = (A, A)
*
@@ -44,7 +65,7 @@ trait Representable[F[_]] extends Serializable { self =>
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> type Pair[A] = (A, A)
*
@@ -133,7 +154,7 @@ object Representable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> type Pair[A] = (A, A)
*
diff --git a/core/src/main/scala/cats/SemigroupK.scala b/core/src/main/scala/cats/SemigroupK.scala
index 4f48a49f92..6b56ca67f4 100644
--- a/core/src/main/scala/cats/SemigroupK.scala
+++ b/core/src/main/scala/cats/SemigroupK.scala
@@ -1,9 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
+import scala.annotation.tailrec
import scala.collection.immutable.{Seq, SortedMap, SortedSet}
-import simulacrum.typeclass
+
import cats.data.Ior
-import scala.annotation.implicitNotFound
+import cats.kernel.compat.scalaVersionSpecific._
/**
* SemigroupK is a universal semigroup which operates on kinds.
@@ -23,20 +45,19 @@ import scala.annotation.implicitNotFound
* The combination operation just depends on the structure of F,
* but not the structure of A.
*/
-@implicitNotFound("Could not find an instance of SemigroupK for ${F}")
-@typeclass trait SemigroupK[F[_]] extends Serializable { self =>
+trait SemigroupK[F[_]] extends Serializable { self =>
/**
* Combine two F[A] values.
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> SemigroupK[List].combineK(List(1, 2), List(3, 4))
* res0: List[Int] = List(1, 2, 3, 4)
* }}}
*/
- @simulacrum.op("<+>", alias = true)
+
def combineK[A](x: F[A], y: F[A]): F[A]
/**
@@ -54,7 +75,7 @@ import scala.annotation.implicitNotFound
*
* {{{
* scala> import cats.{Eval, Later}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val bomb: Eval[Option[Int]] = Later(sys.error("boom"))
* scala> val x: Option[Int] = Some(42)
* scala> x.combineKEval(bomb).value
@@ -65,18 +86,15 @@ import scala.annotation.implicitNotFound
y.map(yy => combineK(x, yy))
/**
- * Given a type A, create a concrete Semigroup[F[A]].
+ * Given a type A, create a concrete `Semigroup[F[A]]`.
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val s: Semigroup[List[Int]] = SemigroupK[List].algebra[Int]
* }}}
*/
- def algebra[A]: Semigroup[F[A]] =
- new Semigroup[F[A]] {
- def combine(x: F[A], y: F[A]): F[A] = self.combineK(x, y)
- }
+ def algebra[A]: Semigroup[F[A]] = combineK(_, _)
/**
* "Compose" with a `G[_]` type to form a `SemigroupK` for `λ[α => F[G[α]]]`.
@@ -85,7 +103,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> type ListOption[A] = List[Option[A]]
* scala> val s: SemigroupK[ListOption] = SemigroupK[List].compose[Option]
* scala> s.combineK(List(Some(1), None, Some(2)), List(Some(3), None))
@@ -110,8 +128,66 @@ import scala.annotation.implicitNotFound
*/
def sum[A, B](fa: F[A], fb: F[B])(implicit F: Functor[F]): F[Either[A, B]] =
combineK(F.map(fa)(Left(_)), F.map(fb)(Right(_)))
+
+ /**
+ * Return `a` combined with itself `n` times.
+ *
+ * Example:
+ * {{{
+ * scala> SemigroupK[List].combineNK(List(1), 5)
+ * res0: List[Int] = List(1, 1, 1, 1, 1)
+ *
+ * }}}
+ */
+ def combineNK[A](a: F[A], n: Int): F[A] =
+ if (n <= 0) throw new IllegalArgumentException("Repeated combining for semigroupKs must have n > 0")
+ else repeatedCombineNK(a, n)
+
+ /**
+ * Return `a` combined with itself more than once.
+ */
+ protected[this] def repeatedCombineNK[A](a: F[A], n: Int): F[A] = {
+ @tailrec def loop(b: F[A], k: Int, extra: F[A]): F[A] =
+ if (k == 1) combineK(b, extra)
+ else {
+ val x = if ((k & 1) == 1) combineK(b, extra) else extra
+ loop(combineK(b, b), k >>> 1, x)
+ }
+ if (n == 1) a else loop(a, n - 1, a)
+ }
+
+ /**
+ * Given a sequence of `as`, combine them and return the total.
+ *
+ * If the sequence is empty, returns None. Otherwise, returns Some(total).
+ *
+ * Example:
+ * {{{
+ * scala> SemigroupK[List].combineAllOptionK(List(List("One"), List("Two"), List("Three")))
+ * res0: Option[List[String]] = Some(List(One, Two, Three))
+ *
+ * scala> SemigroupK[List].combineAllOptionK[String](List.empty)
+ * res1: Option[List[String]] = None
+ * }}}
+ */
+ def combineAllOptionK[A](as: IterableOnce[F[A]]): Option[F[A]] =
+ as.iterator.reduceOption(combineK[A])
+
+ /**
+ * return a semigroupK that reverses the order
+ * so combineK(a, b) == reverse.combineK(b, a)
+ */
+ def reverse: SemigroupK[F] =
+ new SemigroupK[F] {
+ def combineK[A](a: F[A], b: F[A]): F[A] = self.combineK(b, a)
+ // a + a + a + ... is the same when reversed
+ override def combineNK[A](a: F[A], n: Int): F[A] = self.combineNK(a, n)
+ override def reverse = self
+ }
+
}
+@suppressUnusedImportWarningForScalaVersionSpecific
object SemigroupK extends ScalaVersionSpecificMonoidKInstances with SemigroupKInstances0 {
def align[F[_]: SemigroupK: Functor]: Align[F] =
new Align[F] {
@@ -134,10 +210,6 @@ object SemigroupK extends ScalaVersionSpecificMonoidKInstances with SemigroupKIn
cats.instances.sortedMap.catsStdMonoidKForSortedMap[K]
implicit def catsMonoidKForEndo: MonoidK[Endo] = cats.instances.function.catsStdMonoidKForFunction1
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[SemigroupK]] for `F`.
*/
@@ -177,10 +249,6 @@ object SemigroupK extends ScalaVersionSpecificMonoidKInstances with SemigroupKIn
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToSemigroupKOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
trait SemigroupKInstances0 {
diff --git a/core/src/main/scala/cats/Semigroupal.scala b/core/src/main/scala/cats/Semigroupal.scala
index c9218ff19d..3a7f64a63c 100644
--- a/core/src/main/scala/cats/Semigroupal.scala
+++ b/core/src/main/scala/cats/Semigroupal.scala
@@ -1,11 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.kernel.CommutativeSemigroup
import scala.collection.immutable.{Queue, Seq, SortedMap, SortedSet}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
/**
* [[Semigroupal]] captures the idea of composing independent effectful values.
@@ -17,15 +36,14 @@ import scala.annotation.implicitNotFound
* That same idea is also manifested in the form of [[Apply]], and indeed [[Apply]] extends both
* [[Semigroupal]] and [[Functor]] to illustrate this.
*/
-@implicitNotFound("Could not find an instance of Semigroupal for ${F}")
-@typeclass trait Semigroupal[F[_]] extends Serializable {
+trait Semigroupal[F[_]] extends Serializable {
/**
* Combine an `F[A]` and an `F[B]` into an `F[(A, B)]` that maintains the effects of both `fa` and `fb`.
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val noneInt: Option[Int] = None
* scala> val some3: Option[Int] = Some(3)
@@ -49,10 +67,22 @@ import scala.annotation.implicitNotFound
}
object Semigroupal extends ScalaVersionSpecificSemigroupalInstances with SemigroupalArityFunctions {
+ implicit def catsSemigroupalForId: Semigroupal[Id] = catsInstancesForId
implicit def catsSemigroupalForOption: Semigroupal[Option] = cats.instances.option.catsStdInstancesForOption
implicit def catsSemigroupalForTry: Semigroupal[Try] = cats.instances.try_.catsStdInstancesForTry
+
+ /**
+ * @deprecated
+ * Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
+ * (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
+ * We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
+ * However, at this time there are no plans to remove these instances from Cats.
+ *
+ * @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
+ */
implicit def catsSemigroupalForFuture(implicit ec: ExecutionContext): Semigroupal[Future] =
cats.instances.future.catsStdInstancesForFuture(ec)
+
implicit def catsSemigroupalForList: Semigroupal[List] = cats.instances.list.catsStdInstancesForList
implicit def catsSemigroupalForSeq: Semigroupal[Seq] = cats.instances.seq.catsStdInstancesForSeq
implicit def catsSemigroupalForVector: Semigroupal[Vector] = cats.instances.vector.catsStdInstancesForVector
@@ -88,10 +118,6 @@ object Semigroupal extends ScalaVersionSpecificSemigroupalInstances with Semigro
implicit val catsSemigroupalForCommutativeSemigroup: Semigroupal[CommutativeSemigroup] =
cats.instances.invariant.catsInvariantMonoidalCommutativeSemigroup
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Semigroupal]] for `F`.
*/
@@ -128,8 +154,4 @@ object Semigroupal extends ScalaVersionSpecificSemigroupalInstances with Semigro
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToSemigroupalOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/Show.scala b/core/src/main/scala/cats/Show.scala
index de7b208a71..dba5f4f4e0 100644
--- a/core/src/main/scala/cats/Show.scala
+++ b/core/src/main/scala/cats/Show.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import java.util.UUID
@@ -42,18 +63,12 @@ object Show extends ScalaVersionSpecificShowInstances with ShowInstances {
/**
* creates an instance of [[Show]] using the provided function
*/
- def show[A](f: A => String): Show[A] =
- new Show[A] {
- def show(a: A): String = f(a)
- }
+ def show[A](f: A => String): Show[A] = f(_)
/**
* creates an instance of [[Show]] using object toString
*/
- def fromToString[A]: Show[A] =
- new Show[A] {
- def show(a: A): String = a.toString
- }
+ def fromToString[A]: Show[A] = _.toString
final case class Shown(override val toString: String) extends AnyVal
object Shown {
@@ -65,8 +80,7 @@ object Show extends ScalaVersionSpecificShowInstances with ShowInstances {
}
implicit val catsContravariantForShow: Contravariant[Show] = new Contravariant[Show] {
- def contramap[A, B](fa: Show[A])(f: B => A): Show[B] =
- show[B]((fa.show _).compose(f))
+ def contramap[A, B](fa: Show[A])(f: B => A): Show[B] = b => fa.show(f(b))
}
implicit def catsShowForUnit: Show[Unit] = cats.instances.unit.catsStdShowForUnit
@@ -93,9 +107,6 @@ object Show extends ScalaVersionSpecificShowInstances with ShowInstances {
implicit def catsShowForQueue[A: Show]: Show[Queue[A]] = cats.instances.queue.catsStdShowForQueue[A]
implicit def catsShowForEither[A: Show, B: Show]: Show[Either[A, B]] =
cats.instances.either.catsStdShowForEither[A, B]
- implicit def catsShowForSet[A: Show]: Show[Set[A]] = cats.instances.set.catsStdShowForSet[A]
- implicit def catsShowForMap[K: Show, V: Show]: Show[Map[K, V]] = cats.instances.map.catsStdShowForMap[K, V]
- implicit def catsShowForSortedSet[A: Show]: Show[SortedSet[A]] = cats.instances.sortedSet.catsStdShowForSortedSet[A]
implicit def catsShowForSortedMap[K: Show, V: Show]: Show[SortedMap[K, V]] =
cats.instances.sortedMap.catsStdShowForSortedMap[K, V]
@@ -106,8 +117,12 @@ object Show extends ScalaVersionSpecificShowInstances with ShowInstances {
private[cats] trait ShowInstances extends cats.instances.NTupleShowInstances with ShowInstances0 {
implicit def catsShowForFiniteDuration: Show[FiniteDuration] =
cats.instances.finiteDuration.catsStdShowForFiniteDurationUnambiguous
+
+ implicit def catsShowForSortedSet[A: Show]: Show[SortedSet[A]] = cats.instances.sortedSet.catsStdShowForSortedSet[A]
}
private[cats] trait ShowInstances0 {
implicit def catsShowForSeq[A: Show]: Show[Seq[A]] = cats.instances.seq.catsStdShowForSeq[A]
+ implicit def catsShowForMap[K: Show, V: Show]: Show[Map[K, V]] = cats.instances.map.catsStdShowForMap[K, V]
+ implicit def catsShowForSet[A: Show]: Show[Set[A]] = cats.instances.set.catsStdShowForSet[A]
}
diff --git a/core/src/main/scala/cats/StackSafeMonad.scala b/core/src/main/scala/cats/StackSafeMonad.scala
index 8b815dc6f1..c7abf74a15 100644
--- a/core/src/main/scala/cats/StackSafeMonad.scala
+++ b/core/src/main/scala/cats/StackSafeMonad.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import scala.util.{Either, Left, Right}
diff --git a/core/src/main/scala/cats/Traverse.scala b/core/src/main/scala/cats/Traverse.scala
index 0e05fc45a5..2e9df1ea84 100644
--- a/core/src/main/scala/cats/Traverse.scala
+++ b/core/src/main/scala/cats/Traverse.scala
@@ -1,10 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
+import cats.data.Chain
import cats.data.State
import cats.data.StateT
-
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+import cats.kernel.compat.scalaVersionSpecific._
/**
* Traverse, also known as Traversable.
@@ -17,8 +37,7 @@ import scala.annotation.implicitNotFound
*
* See: [[https://www.cs.ox.ac.uk/jeremy.gibbons/publications/iterator.pdf The Essence of the Iterator Pattern]]
*/
-@implicitNotFound("Could not find an instance of Traverse for ${F}")
-@typeclass trait Traverse[F[_]] extends Functor[F] with Foldable[F] with UnorderedTraverse[F] { self =>
+trait Traverse[F[_]] extends Functor[F] with Foldable[F] with UnorderedTraverse[F] { self =>
/**
* Given a function which returns a G effect, thread this effect
@@ -27,7 +46,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> def parseInt(s: String): Option[Int] = Either.catchOnly[NumberFormatException](s.toInt).toOption
* scala> List("1", "2", "3").traverse(parseInt)
* res0: Option[List[Int]] = Some(List(1, 2, 3))
@@ -45,7 +64,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import java.io.IOException
* scala> type IO[A] = Either[IOException, A]
* scala> def debug(msg: String): IO[Unit] = Right(())
@@ -61,7 +80,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> def parseInt(s: String): Option[Int] = Either.catchOnly[NumberFormatException](s.toInt).toOption
* scala> val x = Option(List("1", "two", "3"))
* scala> x.flatTraverse(_.map(parseInt))
@@ -77,7 +96,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val x: List[Option[Int]] = List(Some(1), Some(2))
* scala> val y: List[Option[Int]] = List(None, Some(2))
* scala> x.sequence
@@ -95,7 +114,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val x: List[Option[List[Int]]] = List(Some(List(1, 2)), Some(List(3)))
* scala> val y: List[Option[List[Int]]] = List(None, Some(List(3)))
* scala> x.flatSequence
@@ -116,12 +135,19 @@ import scala.annotation.implicitNotFound
override def map[A, B](fa: F[A])(f: A => B): F[B] =
traverse[Id, A, B](fa)(f)
+ /**
+ * Akin to [[map]], but allows to keep track of a state value
+ * when calling the function.
+ */
+ def mapAccumulate[S, A, B](init: S, fa: F[A])(f: (S, A) => (S, B)): (S, F[B]) =
+ traverse(fa)(a => State(s => f(s, a))).run(init).value
+
/**
* Akin to [[map]], but also provides the value's index in structure
* F when calling the function.
*/
def mapWithIndex[A, B](fa: F[A])(f: (A, Int) => B): F[B] =
- traverse(fa)(a => State((s: Int) => (s + 1, f(a, s)))).runA(0).value
+ mapAccumulate(0, fa)((i, a) => (i + 1) -> f(a, i))._2
/**
* Akin to [[traverse]], but also provides the value's index in
@@ -144,6 +170,46 @@ import scala.annotation.implicitNotFound
def zipWithIndex[A](fa: F[A]): F[(A, Int)] =
mapWithIndex(fa)((a, i) => (a, i))
+ /**
+ * Same as [[traverseWithIndexM]] but the index type is [[Long]] instead of [[Int]].
+ */
+ def traverseWithLongIndexM[G[_], A, B](fa: F[A])(f: (A, Long) => G[B])(implicit G: Monad[G]): G[F[B]] =
+ traverse(fa)(a => StateT((s: Long) => G.map(f(a, s))(b => (s + 1, b)))).runA(0L)
+
+ /**
+ * Same as [[mapWithIndex]] but the index type is [[Long]] instead of [[Int]].
+ */
+ def mapWithLongIndex[A, B](fa: F[A])(f: (A, Long) => B): F[B] =
+ traverseWithLongIndexM[cats.Id, A, B](fa)((a, long) => f(a, long))
+
+ /**
+ * Same as [[zipWithIndex]] but the index type is [[Long]] instead of [[Int]].
+ */
+ def zipWithLongIndex[A](fa: F[A]): F[(A, Long)] =
+ mapWithLongIndex(fa)((a, long) => (a, long))
+
+ /**
+ * If `fa` contains the element at index `idx`,
+ * return the copy of `fa` where the element at `idx` is replaced with `b`.
+ * If there is no element with such an index, return `None`.
+ *
+ * The behavior is consistent with the Scala collection library's
+ * `updated` for collections such as `List`.
+ */
+ def updated_[A, B >: A](fa: F[A], idx: Long, b: B): Option[F[B]] = {
+ if (idx < 0L)
+ None
+ else
+ mapAccumulate(0L, fa)((i, a) =>
+ if (i == idx)
+ (i + 1, b)
+ else
+ (i + 1, a)
+ ) match {
+ case (i, fb) if i > idx => Some(fb)
+ case _ => None
+ }
+ }
override def unorderedTraverse[G[_]: CommutativeApplicative, A, B](sa: F[A])(f: (A) => G[B]): G[F[B]] =
traverse(sa)(f)
@@ -153,10 +219,6 @@ import scala.annotation.implicitNotFound
object Traverse {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Traverse]] for `F`.
*/
@@ -187,10 +249,22 @@ object Traverse {
typeClassInstance.sequence[G, B](self.asInstanceOf[F[G[B]]])
def flatSequence[G[_], B](implicit ev$1: A <:< G[F[B]], G: Applicative[G], F: FlatMap[F]): G[F[B]] =
typeClassInstance.flatSequence[G, B](self.asInstanceOf[F[G[F[B]]]])(G, F)
- def mapWithIndex[B](f: (A, Int) => B): F[B] = typeClassInstance.mapWithIndex[A, B](self)(f)
+ def mapAccumulate[S, B](init: S)(f: (S, A) => (S, B)): (S, F[B]) =
+ typeClassInstance.mapAccumulate[S, A, B](init, self)(f)
+ def mapWithIndex[B](f: (A, Int) => B): F[B] =
+ typeClassInstance.mapWithIndex[A, B](self)(f)
def traverseWithIndexM[G[_], B](f: (A, Int) => G[B])(implicit G: Monad[G]): G[F[B]] =
typeClassInstance.traverseWithIndexM[G, A, B](self)(f)(G)
- def zipWithIndex: F[(A, Int)] = typeClassInstance.zipWithIndex[A](self)
+ def zipWithIndex: F[(A, Int)] =
+ typeClassInstance.zipWithIndex[A](self)
+ def zipWithLongIndex: F[(A, Long)] =
+ typeClassInstance.zipWithLongIndex[A](self)
+ def traverseWithLongIndexM[G[_], B](f: (A, Long) => G[B])(implicit G: Monad[G]): G[F[B]] =
+ typeClassInstance.traverseWithLongIndexM[G, A, B](self)(f)
+ def mapWithLongIndex[B](f: (A, Long) => B): F[B] =
+ typeClassInstance.mapWithLongIndex[A, B](self)(f)
+ def updated_[B >: A](idx: Long, b: B): Option[F[B]] =
+ typeClassInstance.updated_(self, idx, b)
}
trait AllOps[F[_], A]
extends Ops[F, A]
@@ -212,8 +286,26 @@ object Traverse {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToTraverseOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
+ private[cats] def traverseDirectly[G[_], A, B](
+ fa: IterableOnce[A]
+ )(f: A => G[B])(implicit G: StackSafeMonad[G]): G[Chain[B]] = {
+ fa.iterator.foldLeft(G.pure(Chain.empty[B])) { case (accG, a) =>
+ G.map2(accG, f(a)) { case (acc, x) =>
+ acc :+ x
+ }
+ }
+ }
+
+ private[cats] def traverseVoidDirectly[G[_], A, B](
+ fa: IterableOnce[A]
+ )(f: A => G[B])(implicit G: StackSafeMonad[G]): G[Unit] = {
+ val iter = fa.iterator
+ if (iter.hasNext) {
+ val first = iter.next()
+ G.void(iter.foldLeft(f(first)) { case (g, a) =>
+ G.productR(g)(f(a))
+ })
+ } else G.unit
+ }
}
diff --git a/core/src/main/scala/cats/TraverseFilter.scala b/core/src/main/scala/cats/TraverseFilter.scala
index 3ec382c1df..9926efc321 100644
--- a/core/src/main/scala/cats/TraverseFilter.scala
+++ b/core/src/main/scala/cats/TraverseFilter.scala
@@ -1,10 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
-import cats.data.State
-import simulacrum.{noop, typeclass}
+import cats.data.{Chain, State}
+import cats.kernel.compat.scalaVersionSpecific._
-import scala.annotation.implicitNotFound
-import scala.collection.immutable.{HashSet, TreeSet}
+import scala.collection.immutable.{IntMap, TreeSet}
/**
* `TraverseFilter`, also known as `Witherable`, represents list-like structures
@@ -14,8 +34,6 @@ import scala.collection.immutable.{HashSet, TreeSet}
* Based on Haskell's [[https://hackage.haskell.org/package/witherable-0.1.3.3/docs/Data-Witherable.html Data.Witherable]]
*/
-@implicitNotFound("Could not find an instance of TraverseFilter for ${F}")
-@typeclass
trait TraverseFilter[F[_]] extends FunctorFilter[F] {
def traverse: Traverse[F]
@@ -28,7 +46,7 @@ trait TraverseFilter[F[_]] extends FunctorFilter[F] {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val m: Map[Int, String] = Map(1 -> "one", 3 -> "three")
* scala> val l: List[Int] = List(1, 2, 3, 4)
* scala> def asString(i: Int): Eval[Option[String]] = Now(m.get(i))
@@ -39,15 +57,31 @@ trait TraverseFilter[F[_]] extends FunctorFilter[F] {
*/
def traverseFilter[G[_], A, B](fa: F[A])(f: A => G[Option[B]])(implicit G: Applicative[G]): G[F[B]]
+ /**
+ * A combined [[traverse]] and [[collect]].
+ *
+ * scala> import cats.syntax.all._
+ * scala> val m: Map[Int, String] = Map(1 -> "one", 2 -> "two")
+ * scala> val l: List[Int] = List(1, 2, 3, 4)
+ * scala> def asString: PartialFunction[Int, Eval[Option[String]]] = { case n if n % 2 == 0 => Now(m.get(n)) }
+ * scala> val result: Eval[List[Option[String]]] = l.traverseCollect(asString)
+ * scala> result.value
+ * res0: List[Option[String]] = List(Some(two), None)
+ */
+ def traverseCollect[G[_], A, B](fa: F[A])(f: PartialFunction[A, G[B]])(implicit G: Applicative[G]): G[F[B]] = {
+ val optF = f.lift
+ traverseFilter(fa)(a => Traverse[Option].sequence(optF(a)))
+ }
+
/**
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val a: List[Either[String, Option[Int]]] = List(Right(Some(1)), Right(Some(5)), Right(Some(3)))
* scala> val b: Either[String, List[Int]] = TraverseFilter[List].sequenceFilter(a)
* b: Either[String, List[Int]] = Right(List(1, 5, 3))
* }}}
*/
- @noop
+
def sequenceFilter[G[_], A](fgoa: F[G[Option[A]]])(implicit G: Applicative[G]): G[F[A]] =
traverseFilter(fgoa)(identity)
@@ -59,7 +93,7 @@ trait TraverseFilter[F[_]] extends FunctorFilter[F] {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val l: List[Int] = List(1, 2, 3, 4)
* scala> def odd(i: Int): Eval[Boolean] = Now(i % 2 == 1)
* scala> val res: Eval[List[Int]] = l.filterA(odd)
@@ -105,23 +139,26 @@ trait TraverseFilter[F[_]] extends FunctorFilter[F] {
/**
* Removes duplicate elements from a list, keeping only the first occurrence.
- * This is usually faster than ordDistinct, especially for things that have a slow comparion (like String).
+ * This is usually faster than ordDistinct, especially for things that have a slow comparison (like String).
*/
def hashDistinct[A](fa: F[A])(implicit H: Hash[A]): F[A] =
- traverseFilter[State[HashSet[A], *], A, A](fa)(a =>
- State(alreadyIn => if (alreadyIn(a)) (alreadyIn, None) else (alreadyIn + a, Some(a)))
- )
- .run(HashSet.empty)
- .value
- ._2
+ traverseFilter(fa) { a =>
+ State { (distinct: IntMap[List[A]]) =>
+ val ahash = H.hash(a)
+ distinct.get(ahash) match {
+ case None => (distinct.updated(ahash, a :: Nil), Some(a))
+ case Some(existing) =>
+ if (Traverse[List].contains_(existing, a))
+ (distinct, None)
+ else
+ (distinct.updated(ahash, a :: existing), Some(a))
+ }
+ }
+ }.run(IntMap.empty).value._2
}
object TraverseFilter {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[TraverseFilter]] for `F`.
*/
@@ -167,8 +204,15 @@ object TraverseFilter {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToTraverseFilterOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
+ private[cats] def traverseFilterDirectly[G[_], A, B](
+ fa: IterableOnce[A]
+ )(f: A => G[Option[B]])(implicit G: StackSafeMonad[G]): G[Chain[B]] = {
+ fa.iterator.foldLeft(G.pure(Chain.empty[B])) { case (bldrG, a) =>
+ G.map2(bldrG, f(a)) {
+ case (acc, Some(b)) => acc :+ b
+ case (acc, None) => acc
+ }
+ }
+ }
}
diff --git a/core/src/main/scala/cats/UnorderedFoldable.scala b/core/src/main/scala/cats/UnorderedFoldable.scala
index 1ed30c2cb3..f903b24882 100644
--- a/core/src/main/scala/cats/UnorderedFoldable.scala
+++ b/core/src/main/scala/cats/UnorderedFoldable.scala
@@ -1,22 +1,67 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
import cats.kernel.CommutativeMonoid
import scala.collection.immutable.{Queue, Seq, SortedMap, SortedSet}
import scala.util.Try
-import simulacrum.{noop, typeclass}
-import scala.annotation.implicitNotFound
/**
* `UnorderedFoldable` is like a `Foldable` for unordered containers.
*/
-@implicitNotFound("Could not find an instance of UnorderedFoldable for ${F}")
-@typeclass trait UnorderedFoldable[F[_]] extends Serializable {
+trait UnorderedFoldable[F[_]] extends Serializable {
def unorderedFoldMap[A, B: CommutativeMonoid](fa: F[A])(f: A => B): B
def unorderedFold[A: CommutativeMonoid](fa: F[A]): A =
unorderedFoldMap(fa)(identity)
+ /**
+ * Fold in a [[CommutativeApplicative]] context by mapping the `A` values to `G[B]`. combining
+ * the `B` values using the given `CommutativeMonoid[B]` instance.
+ *
+ * {{{
+ * scala> import cats.UnorderedFoldable
+ * scala> import cats.syntax.all._
+ * scala> val evenNumbers = Set(2,4,6,8,10)
+ * scala> val evenOpt: Int => Option[Int] =
+ * | i => if (i % 2 == 0) Some(i) else None
+ * scala> UnorderedFoldable[Set].unorderedFoldMapA(evenNumbers)(evenOpt)
+ * res0: Option[Int] = Some(30)
+ * scala> UnorderedFoldable[Set].unorderedFoldMapA(evenNumbers + 11)(evenOpt)
+ * res1: Option[Int] = None
+ * }}}
+ */
+ def unorderedFoldMapA[G[_], A, B](fa: F[A])(
+ f: A => G[B]
+ )(implicit G: CommutativeApplicative[G], B: CommutativeMonoid[B]): G[B] =
+ unorderedFoldMap(fa)(f)(CommutativeApplicative.commutativeMonoidFor)
+
+ /**
+ * Tests if `fa` contains `v` using the `Eq` instance for `A`
+ */
+ def contains_[A](fa: F[A], v: A)(implicit ev: Eq[A]): Boolean =
+ exists(fa)(a => ev.eqv(a, v))
+
/**
* Returns true if there are no elements. Otherwise false.
*/
@@ -57,7 +102,7 @@ import scala.annotation.implicitNotFound
*
* For example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val map1 = Map[Int, String]()
* scala> val p1: String => Boolean = _.length > 0
* scala> UnorderedFoldable[Map[Int, *]].count(map1)(p1)
@@ -69,14 +114,19 @@ import scala.annotation.implicitNotFound
* res1: Long = 2
* }}}
*/
- @noop
+
def count[A](fa: F[A])(p: A => Boolean): Long =
unorderedFoldMap(fa)(a => if (p(a)) 1L else 0L)
}
+private[cats] trait UnorderedFoldableLowPriority {
+ implicit def catsTraverseForSeq: Traverse[Seq] = cats.instances.seq.catsStdInstancesForSeq
+}
+
object UnorderedFoldable
extends ScalaVersionSpecificTraverseInstances
- with cats.instances.NTupleUnorderedFoldableInstances {
+ with cats.instances.NTupleUnorderedFoldableInstances
+ with UnorderedFoldableLowPriority {
private val orEvalMonoid: CommutativeMonoid[Eval[Boolean]] = new CommutativeMonoid[Eval[Boolean]] {
val empty: Eval[Boolean] = Eval.False
@@ -101,7 +151,6 @@ object UnorderedFoldable
implicit def catsNonEmptyTraverseForId: NonEmptyTraverse[Id] = catsInstancesForId
implicit def catsTraverseForOption: Traverse[Option] = cats.instances.option.catsStdInstancesForOption
implicit def catsTraverseForList: Traverse[List] = cats.instances.list.catsStdInstancesForList
- implicit def catsTraverseForSeq: Traverse[Seq] = cats.instances.seq.catsStdInstancesForSeq
implicit def catsTraverseForVector: Traverse[Vector] = cats.instances.vector.catsStdInstancesForVector
implicit def catsTraverseForQueue: Traverse[Queue] = cats.instances.queue.catsStdInstancesForQueue
implicit def catsUnorderedTraverseForSet: UnorderedTraverse[Set] = cats.instances.set.catsStdInstancesForSet
@@ -116,13 +165,9 @@ object UnorderedFoldable
implicit def catsTraverseForTry: Traverse[Try] = cats.instances.try_.catsStdInstancesForTry
@deprecated("Use catsStdInstancesForTuple2 in cats.instances.NTupleMonadInstances", "2.4.0")
- def catsInstancesForTuple[A]: Traverse[(A, *)] with Reducible[(A, *)] =
+ def catsInstancesForTuple[A]: Traverse[(A, *)] & Reducible[(A, *)] =
cats.instances.tuple.catsStdInstancesForTuple2[A]
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[UnorderedFoldable]] for `F`.
*/
@@ -146,6 +191,10 @@ object UnorderedFoldable
def unorderedFoldMap[B](f: A => B)(implicit ev$1: CommutativeMonoid[B]): B =
typeClassInstance.unorderedFoldMap[A, B](self)(f)
def unorderedFold(implicit ev$1: CommutativeMonoid[A]): A = typeClassInstance.unorderedFold[A](self)
+ def unorderedFoldMapA[G[_], B](
+ f: A => G[B]
+ )(implicit ev$1: CommutativeApplicative[G], ev$2: CommutativeMonoid[B]): G[B] =
+ typeClassInstance.unorderedFoldMapA[G, A, B](self)(f)
def isEmpty: Boolean = typeClassInstance.isEmpty[A](self)
def nonEmpty: Boolean = typeClassInstance.nonEmpty[A](self)
def exists(p: A => Boolean): Boolean = typeClassInstance.exists[A](self)(p)
@@ -165,9 +214,4 @@ object UnorderedFoldable
}
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToUnorderedFoldableOps
-
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/UnorderedTraverse.scala b/core/src/main/scala/cats/UnorderedTraverse.scala
index d9322c1e44..8bd7baffda 100644
--- a/core/src/main/scala/cats/UnorderedTraverse.scala
+++ b/core/src/main/scala/cats/UnorderedTraverse.scala
@@ -1,13 +1,30 @@
-package cats
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
+package cats
/**
* `UnorderedTraverse` is like a `Traverse` for unordered containers.
*/
-@implicitNotFound("Could not find an instance of UnorderedTraverse for ${F}")
-@typeclass trait UnorderedTraverse[F[_]] extends UnorderedFoldable[F] {
+trait UnorderedTraverse[F[_]] extends UnorderedFoldable[F] {
def unorderedTraverse[G[_]: CommutativeApplicative, A, B](sa: F[A])(f: A => G[B]): G[F[B]]
def unorderedSequence[G[_]: CommutativeApplicative, A](fga: F[G[A]]): G[F[A]] =
@@ -16,10 +33,6 @@ import scala.annotation.implicitNotFound
object UnorderedTraverse {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[UnorderedTraverse]] for `F`.
*/
@@ -61,8 +74,4 @@ object UnorderedTraverse {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToUnorderedTraverseOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/arrow/Arrow.scala b/core/src/main/scala/cats/arrow/Arrow.scala
index de932a2280..0d041f4074 100644
--- a/core/src/main/scala/cats/arrow/Arrow.scala
+++ b/core/src/main/scala/cats/arrow/Arrow.scala
@@ -1,14 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package arrow
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
/**
* Must obey the laws defined in cats.laws.ArrowLaws.
*/
-@implicitNotFound("Could not find an instance of Arrow for ${F}")
-@typeclass trait Arrow[F[_, _]] extends Category[F] with Strong[F] { self =>
+trait Arrow[F[_, _]] extends Category[F] with Strong[F] { self =>
/**
* Lift a function into the context of an Arrow.
@@ -35,7 +52,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.arrow.Arrow
* scala> val toLong: Int => Long = _.toLong
* scala> val toDouble: Float => Double = _.toDouble
@@ -47,7 +64,7 @@ import scala.annotation.implicitNotFound
* Note that the arrow laws do not guarantee the non-interference between the _effects_ of
* `f` and `g` in the context of F. This means that `f *** g` may not be equivalent to `g *** f`.
*/
- @simulacrum.op("***", alias = true)
+
def split[A, B, C, D](f: F[A, B], g: F[C, D]): F[(A, C), (B, D)] =
andThen(first(f), second(g))
@@ -56,7 +73,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val addEmpty: Int => Int = _ + 0
* scala> val multiplyEmpty: Int => Double= _ * 1d
* scala> val f: Int => (Int, Double) = addEmpty &&& multiplyEmpty
@@ -67,17 +84,13 @@ import scala.annotation.implicitNotFound
* Note that the arrow laws do not guarantee the non-interference between the _effects_ of
* `f` and `g` in the context of F. This means that `f &&& g` may not be equivalent to `g &&& f`.
*/
- @simulacrum.op("&&&", alias = true)
+
def merge[A, B, C](f: F[A, B], g: F[A, C]): F[A, (B, C)] =
andThen(lift((x: A) => (x, x)), split(f, g))
}
object Arrow {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Arrow]] for `F`.
*/
@@ -119,8 +132,4 @@ object Arrow {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToArrowOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/arrow/ArrowChoice.scala b/core/src/main/scala/cats/arrow/ArrowChoice.scala
index 9423883f69..c76745e9ac 100644
--- a/core/src/main/scala/cats/arrow/ArrowChoice.scala
+++ b/core/src/main/scala/cats/arrow/ArrowChoice.scala
@@ -1,14 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package arrow
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
/**
* Must obey the laws defined in cats.laws.ArrowChoiceLaws.
*/
-@implicitNotFound("Could not find an instance of ArrowChoice for ${F}")
-@typeclass trait ArrowChoice[F[_, _]] extends Arrow[F] with Choice[F] { self =>
+trait ArrowChoice[F[_, _]] extends Arrow[F] with Choice[F] { self =>
/**
* ArrowChoice yields Arrows with choice, allowing distribution
@@ -21,7 +38,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val toLong: Int => Long = _.toLong
* scala> val toDouble: Float => Double = _.toDouble
* scala> val f: Either[Int, Float] => Either[Long, Double] = toLong +++ toDouble
@@ -31,7 +48,7 @@ import scala.annotation.implicitNotFound
* res1: Either[Long,Double] = Right(3.0)
* }}}
*/
- @simulacrum.op("+++", alias = true)
+
def choose[A, B, C, D](f: F[A, C])(g: F[B, D]): F[Either[A, B], Either[C, D]]
def left[A, B, C](fab: F[A, B]): F[Either[A, C], Either[B, C]] =
@@ -46,10 +63,6 @@ import scala.annotation.implicitNotFound
object ArrowChoice {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[ArrowChoice]] for `F`.
*/
@@ -91,8 +104,4 @@ object ArrowChoice {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToArrowChoiceOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/arrow/Category.scala b/core/src/main/scala/cats/arrow/Category.scala
index 74ee6e284e..587ffb23cd 100644
--- a/core/src/main/scala/cats/arrow/Category.scala
+++ b/core/src/main/scala/cats/arrow/Category.scala
@@ -1,14 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package arrow
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
/**
* Must obey the laws defined in cats.laws.CategoryLaws.
*/
-@implicitNotFound("Could not find an instance of Category for ${F}")
-@typeclass trait Category[F[_, _]] extends Compose[F] { self =>
+trait Category[F[_, _]] extends Compose[F] { self =>
def id[A]: F[A, A]
@@ -27,10 +44,6 @@ import scala.annotation.implicitNotFound
object Category {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Category]] for `F`.
*/
@@ -68,8 +81,4 @@ object Category {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToCategoryOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/arrow/Choice.scala b/core/src/main/scala/cats/arrow/Choice.scala
index 9fdd9b6fe3..d5259456d2 100644
--- a/core/src/main/scala/cats/arrow/Choice.scala
+++ b/core/src/main/scala/cats/arrow/Choice.scala
@@ -1,11 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package arrow
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
-@implicitNotFound("Could not find an instance of Choice for ${F}")
-@typeclass trait Choice[F[_, _]] extends Category[F] {
+trait Choice[F[_, _]] extends Category[F] {
/**
* Given two `F`s (`f` and `g`) with a common target type, create a new `F`
@@ -14,7 +31,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val b: Boolean => String = _.toString + " is a boolean"
* scala> val i: Int => String = _.toString + " is an integer"
* scala> val f: (Either[Boolean, Int]) => String = b ||| i
@@ -26,7 +43,7 @@ import scala.annotation.implicitNotFound
* res0: String = false is a boolean
* }}}
*/
- @simulacrum.op("|||", alias = true)
+
def choice[A, B, C](f: F[A, C], g: F[B, C]): F[Either[A, B], C]
/**
@@ -35,7 +52,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val f: (Either[Int, Int]) => Int = Choice[Function1].codiagonal[Int]
*
* scala> f(Right(3))
@@ -50,10 +67,6 @@ import scala.annotation.implicitNotFound
object Choice {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Choice]] for `F`.
*/
@@ -93,8 +106,4 @@ object Choice {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToChoiceOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/arrow/CommutativeArrow.scala b/core/src/main/scala/cats/arrow/CommutativeArrow.scala
index 8042ca58a4..0d72afa443 100644
--- a/core/src/main/scala/cats/arrow/CommutativeArrow.scala
+++ b/core/src/main/scala/cats/arrow/CommutativeArrow.scala
@@ -1,24 +1,37 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package arrow
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
/**
* In a Commutative Arrow F[_, _], the split operation (or `***`) is commutative,
* which means that there is non-interference between the effect of the paired arrows.
*
* Must obey the laws in CommutativeArrowLaws
*/
-@implicitNotFound("Could not find an instance of CommutativeArrow for ${F}")
-@typeclass trait CommutativeArrow[F[_, _]] extends Arrow[F]
+trait CommutativeArrow[F[_, _]] extends Arrow[F]
object CommutativeArrow {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[CommutativeArrow]] for `F`.
*/
@@ -58,8 +71,4 @@ object CommutativeArrow {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToCommutativeArrowOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/arrow/Compose.scala b/core/src/main/scala/cats/arrow/Compose.scala
index 7342c61e07..d39648161e 100644
--- a/core/src/main/scala/cats/arrow/Compose.scala
+++ b/core/src/main/scala/cats/arrow/Compose.scala
@@ -1,16 +1,34 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package arrow
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
/**
* Must obey the laws defined in cats.laws.ComposeLaws.
*
* Here's how you can use `>>>` and `<<<`
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val f : Int => Int = (_ + 1)
* scala> val g : Int => Int = (_ * 100)
* scala> (f >>> g)(3)
@@ -19,13 +37,10 @@ import scala.annotation.implicitNotFound
* res1: Int = 301
* }}}
*/
-@implicitNotFound("Could not find an instance of Compose for ${F}")
-@typeclass trait Compose[F[_, _]] extends Serializable { self =>
+trait Compose[F[_, _]] extends Serializable { self =>
- @simulacrum.op("<<<", alias = true)
def compose[A, B, C](f: F[B, C], g: F[A, B]): F[A, C]
- @simulacrum.op(">>>", alias = true)
def andThen[A, B, C](f: F[A, B], g: F[B, C]): F[A, C] =
compose(g, f)
@@ -34,24 +49,17 @@ import scala.annotation.implicitNotFound
def combineK[A](f1: F[A, A], f2: F[A, A]): F[A, A] = self.compose(f1, f2)
}
- def algebra[A]: Semigroup[F[A, A]] =
- new Semigroup[F[A, A]] {
- def combine(f1: F[A, A], f2: F[A, A]): F[A, A] = self.compose(f1, f2)
- }
+ def algebra[A]: Semigroup[F[A, A]] = compose(_, _)
}
object Compose {
- implicit def catsInstancesForFunction1: ArrowChoice[Function1] with CommutativeArrow[Function1] =
+ implicit def catsInstancesForFunction1: ArrowChoice[Function1] & CommutativeArrow[Function1] =
cats.instances.function.catsStdInstancesForFunction1
implicit def catsComposeForMap: Compose[Map] = cats.instances.map.catsStdComposeForMap
- implicit def catsInstancesForPartialFunction: ArrowChoice[PartialFunction] with CommutativeArrow[PartialFunction] =
+ implicit def catsInstancesForPartialFunction: ArrowChoice[PartialFunction] & CommutativeArrow[PartialFunction] =
cats.instances.partialFunction.catsStdInstancesForPartialFunction
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Compose]] for `F`.
*/
@@ -91,8 +99,4 @@ object Compose {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToComposeOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/arrow/FunctionK.scala b/core/src/main/scala/cats/arrow/FunctionK.scala
index 4f513f0ac8..a371919461 100644
--- a/core/src/main/scala/cats/arrow/FunctionK.scala
+++ b/core/src/main/scala/cats/arrow/FunctionK.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package arrow
diff --git a/core/src/main/scala/cats/arrow/FunctionKLift.scala b/core/src/main/scala/cats/arrow/FunctionKLift.scala
new file mode 100644
index 0000000000..7f5dafb525
--- /dev/null
+++ b/core/src/main/scala/cats/arrow/FunctionKLift.scala
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats
+package arrow
+
+private[arrow] trait FunctionKLift {
+ protected type τ[F[_], G[_]]
+
+ /**
+ * Lifts function `f` of `F[A] => G[A]` into a `FunctionK[F, G]`.
+ *
+ * {{{
+ * def headOption[A](list: List[A]): Option[A] = list.headOption
+ * val lifted = FunctionK.liftFunction[List, Option](headOption)
+ * }}}
+ *
+ * Note: The weird `τ[F, G]` parameter is there to compensate for
+ * the lack of polymorphic function types in Scala 2.
+ *
+ * It is present in the Scala 3 API to simplify cross-compilation.
+ */
+ def liftFunction[F[_], G[_]](f: F[τ[F, G]] => G[τ[F, G]]): FunctionK[F, G] =
+ new FunctionK[F, G] {
+ def apply[A](fa: F[A]): G[A] = f.asInstanceOf[F[A] => G[A]](fa)
+ }
+}
diff --git a/core/src/main/scala/cats/arrow/Profunctor.scala b/core/src/main/scala/cats/arrow/Profunctor.scala
index 491421ae60..8a699aed30 100644
--- a/core/src/main/scala/cats/arrow/Profunctor.scala
+++ b/core/src/main/scala/cats/arrow/Profunctor.scala
@@ -1,24 +1,41 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package arrow
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
/**
* A [[Profunctor]] is a [[Contravariant]] functor on its first type parameter
* and a [[Functor]] on its second type parameter.
*
* Must obey the laws defined in cats.laws.ProfunctorLaws.
*/
-@implicitNotFound("Could not find an instance of Profunctor for ${F}")
-@typeclass trait Profunctor[F[_, _]] extends Serializable { self =>
+trait Profunctor[F[_, _]] extends Serializable { self =>
/**
* Contramap on the first type parameter and map on the second type parameter
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.arrow.Profunctor
* scala> val fab: Double => Double = x => x + 0.3
* scala> val f: Int => Double = x => x.toDouble / 2
@@ -80,10 +97,6 @@ object Profunctor {
implicit def catsStrongForPartialFunction: Strong[PartialFunction] =
cats.instances.partialFunction.catsStdInstancesForPartialFunction
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Profunctor]] for `F`.
*/
@@ -124,8 +137,4 @@ object Profunctor {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToProfunctorOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/arrow/Strong.scala b/core/src/main/scala/cats/arrow/Strong.scala
index ef76fa4e2b..561ae1ffd1 100644
--- a/core/src/main/scala/cats/arrow/Strong.scala
+++ b/core/src/main/scala/cats/arrow/Strong.scala
@@ -1,21 +1,38 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package arrow
-import simulacrum.typeclass
-import scala.annotation.implicitNotFound
-
/**
* Must obey the laws defined in cats.laws.StrongLaws.
*/
-@implicitNotFound("Could not find an instance of Strong for ${F}")
-@typeclass trait Strong[F[_, _]] extends Profunctor[F] {
+trait Strong[F[_, _]] extends Profunctor[F] {
/**
* Create a new `F` that takes two inputs, but only modifies the first input
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.arrow.Strong
* scala> val f: Int => Int = _ * 2
* scala> val fab = Strong[Function1].first[Int,Int,Int](f)
@@ -30,7 +47,7 @@ import scala.annotation.implicitNotFound
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.arrow.Strong
* scala> val f: Int => Int = _ * 2
* scala> val fab = Strong[Function1].second[Int,Int,Int](f)
@@ -43,10 +60,6 @@ import scala.annotation.implicitNotFound
object Strong {
- /* ======================================================================== */
- /* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
- /* ======================================================================== */
-
/**
* Summon an instance of [[Strong]] for `F`.
*/
@@ -86,8 +99,4 @@ object Strong {
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToStrongOps
- /* ======================================================================== */
- /* END OF SIMULACRUM-MANAGED CODE */
- /* ======================================================================== */
-
}
diff --git a/core/src/main/scala/cats/conversions/VarianceConversions.scala b/core/src/main/scala/cats/conversions/VarianceConversions.scala
index c463a3d077..6d8cd4640b 100644
--- a/core/src/main/scala/cats/conversions/VarianceConversions.scala
+++ b/core/src/main/scala/cats/conversions/VarianceConversions.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package conversions
import cats.arrow.Profunctor
diff --git a/core/src/main/scala/cats/conversions/all.scala b/core/src/main/scala/cats/conversions/all.scala
index 676b563542..8692b921c1 100644
--- a/core/src/main/scala/cats/conversions/all.scala
+++ b/core/src/main/scala/cats/conversions/all.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.conversions
trait AllConversions extends VarianceConversions
diff --git a/core/src/main/scala/cats/conversions/package.scala b/core/src/main/scala/cats/conversions/package.scala
index ac47bccbf5..dba42ee66c 100644
--- a/core/src/main/scala/cats/conversions/package.scala
+++ b/core/src/main/scala/cats/conversions/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package object conversions {
diff --git a/core/src/main/scala/cats/data/AbstractNonEmptyInstances.scala b/core/src/main/scala/cats/data/AbstractNonEmptyInstances.scala
index b5f4eacd3e..dba28aa712 100644
--- a/core/src/main/scala/cats/data/AbstractNonEmptyInstances.scala
+++ b/core/src/main/scala/cats/data/AbstractNonEmptyInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -5,17 +26,23 @@ abstract private[data] class AbstractNonEmptyInstances[F[_], NonEmptyF[_]](impli
MF: Monad[F],
CF: CoflatMap[F],
TF: Traverse[F],
- SF: SemigroupK[F]
+ SF: Alternative[F]
) extends Bimonad[NonEmptyF]
with NonEmptyTraverse[NonEmptyF]
- with SemigroupK[NonEmptyF] {
+ with NonEmptyAlternative[NonEmptyF] {
val monadInstance = MF.asInstanceOf[Monad[NonEmptyF]]
val coflatMapInstance = CF.asInstanceOf[CoflatMap[NonEmptyF]]
val traverseInstance = Traverse[F].asInstanceOf[Traverse[NonEmptyF]]
- val semiGroupKInstance = SemigroupK[F].asInstanceOf[SemigroupK[NonEmptyF]]
+ val alternativeInstance = Alternative[F].asInstanceOf[Alternative[NonEmptyF]]
def combineK[A](a: NonEmptyF[A], b: NonEmptyF[A]): NonEmptyF[A] =
- semiGroupKInstance.combineK(a, b)
+ alternativeInstance.combineK(a, b)
+
+ override def prependK[A](a: A, fa: NonEmptyF[A]): NonEmptyF[A] =
+ alternativeInstance.prependK(a, fa)
+
+ override def appendK[A](fa: NonEmptyF[A], a: A): NonEmptyF[A] =
+ alternativeInstance.appendK(fa, a)
def pure[A](x: A): NonEmptyF[A] = monadInstance.pure(x)
diff --git a/core/src/main/scala/cats/data/AndThen.scala b/core/src/main/scala/cats/data/AndThen.scala
index af5f8d546b..9081968b68 100644
--- a/core/src/main/scala/cats/data/AndThen.scala
+++ b/core/src/main/scala/cats/data/AndThen.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -289,7 +310,7 @@ abstract private[data] class AndThenInstances0 extends AndThenInstances1 {
* [[cats.arrow.CommutativeArrow CommutativeArrow]] instances
* for [[AndThen]].
*/
- implicit val catsDataArrowForAndThen: ArrowChoice[AndThen] with CommutativeArrow[AndThen] =
+ implicit val catsDataArrowForAndThen: ArrowChoice[AndThen] & CommutativeArrow[AndThen] =
new ArrowChoice[AndThen] with CommutativeArrow[AndThen] {
// Piggybacking on the instance for Function1
private[this] val fn1 = instances.all.catsStdInstancesForFunction1
diff --git a/core/src/main/scala/cats/data/Binested.scala b/core/src/main/scala/cats/data/Binested.scala
index 22a822c44e..7ab52ea2b8 100644
--- a/core/src/main/scala/cats/data/Binested.scala
+++ b/core/src/main/scala/cats/data/Binested.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -13,7 +34,7 @@ import cats.arrow._
* {{{
* scala> import cats.Bifunctor
* scala> import cats.data.Binested
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val eitherListOption: Either[List[Int], Option[String]] = Right(Some("cats"))
* scala> val f: Int => String = _.toString
* scala> val g: String => String = _ + "-bifunctor"
diff --git a/core/src/main/scala/cats/data/Chain.scala b/core/src/main/scala/cats/data/Chain.scala
index b1decfdaa4..707ca8f106 100644
--- a/core/src/main/scala/cats/data/Chain.scala
+++ b/core/src/main/scala/cats/data/Chain.scala
@@ -1,19 +1,80 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* This file is derived in part from https://github.com/scala/scala/blob/v2.13.8/src/library/scala/collection/Iterable.scala
+ * Modified by Typelevel for redistribution in Cats.
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ * Scala
+ * Copyright (c) 2002-2022 EPFL
+ * Copyright (c) 2011-2022 Lightbend, Inc.
+ *
+ * Scala includes software developed at
+ * LAMP/EPFL (https://lamp.epfl.ch/) and
+ * Lightbend, Inc. (https://www.lightbend.com/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package cats
package data
-import Chain._
-import cats.kernel.instances.StaticMethods
+import cats.instances.StaticMethods
+import cats.kernel.compat.scalaVersionSpecific._
+import cats.kernel.instances.{StaticMethods => KernelStaticMethods}
import scala.annotation.tailrec
-import scala.collection.immutable.{IndexedSeq => ImIndexedSeq, SortedMap, TreeSet}
+import scala.collection.immutable
+import scala.collection.immutable.SortedMap
+import scala.collection.mutable
import scala.collection.mutable.ListBuffer
+import Chain.{
+ empty,
+ fromSeq,
+ nil,
+ one,
+ sentinel,
+ traverseFilterViaChain,
+ traverseViaChain,
+ Append,
+ ChainIterator,
+ ChainReverseIterator,
+ Empty,
+ NonEmpty,
+ Singleton,
+ Wrap
+}
+
/**
* Trivial catenable sequence. Supports O(1) append, and (amortized)
* O(1) `uncons`, such that walking the sequence via N successive `uncons`
* steps takes O(N).
*/
-sealed abstract class Chain[+A] {
+sealed abstract class Chain[+A] extends ChainCompat[A] {
/**
* Returns the head and tail of this Chain if non empty, none otherwise. Amortized O(1).
@@ -104,13 +165,17 @@ sealed abstract class Chain[+A] {
/**
* Returns true if there are no elements in this collection.
*/
- def isEmpty: Boolean = !this.isInstanceOf[Chain.NonEmpty[_]]
+ def isEmpty: Boolean = !this.isInstanceOf[Chain.NonEmpty[?]]
/**
* Returns false if there are no elements in this collection.
*/
final def nonEmpty: Boolean = !isEmpty
+ // Quick check whether the chain is either empty or contains one element only.
+ @inline private def isEmptyOrSingleton: Boolean =
+ isEmpty || this.isInstanceOf[Chain.Singleton[?]]
+
/**
* Concatenates this with `c` in O(1) runtime.
*/
@@ -191,6 +256,99 @@ sealed abstract class Chain[+A] {
result
}
+ /**
+ * take a certain amount of items from the front of the Chain
+ */
+ final def take(count: Long): Chain[A] = {
+ // invariant count >= 1
+ @tailrec
+ def go(lhs: Chain[A], count: Long, arg: NonEmpty[A], rhs: Chain[A]): Chain[A] =
+ arg match {
+ case Wrap(seq) =>
+ if (count == 1) {
+ lhs.append(seq.head)
+ } else {
+ // count > 1
+ val taken =
+ if (count < Int.MaxValue) seq.take(count.toInt)
+ else seq.take(Int.MaxValue)
+ // we may have not taken all of count
+ val newCount = count - taken.length
+ val wrapped = Wrap(taken)
+ // this is more efficient than using concat
+ val newLhs = if (lhs.isEmpty) wrapped else Append(lhs, wrapped)
+ rhs match {
+ case rhsNE: NonEmpty[A] if newCount > 0L =>
+ // we have to keep taking on the rhs
+ go(newLhs, newCount, rhsNE, Empty)
+ case _ =>
+ newLhs
+ }
+ }
+ case Append(l, r) =>
+ go(lhs, count, l, if (rhs.isEmpty) r else Append(r, rhs))
+ case s @ Singleton(_) =>
+ // due to the invariant count >= 1
+ val newLhs = if (lhs.isEmpty) s else Append(lhs, s)
+ rhs match {
+ case rhsNE: NonEmpty[A] if count > 1L =>
+ go(newLhs, count - 1L, rhsNE, Empty)
+ case _ => newLhs
+ }
+ }
+
+ this match {
+ case ne: NonEmpty[A] if count > 0L =>
+ go(Empty, count, ne, Empty)
+ case _ => Empty
+ }
+ }
+
+ /**
+ * take a certain amount of items from the back of the Chain
+ */
+ final def takeRight(count: Long): Chain[A] = {
+ // invariant count >= 1
+ @tailrec
+ def go(lhs: Chain[A], count: Long, arg: NonEmpty[A], rhs: Chain[A]): Chain[A] =
+ arg match {
+ case Wrap(seq) =>
+ if (count == 1L) {
+ seq.last +: rhs
+ } else {
+ // count > 1
+ val taken =
+ if (count < Int.MaxValue) seq.takeRight(count.toInt)
+ else seq.takeRight(Int.MaxValue)
+ // we may have not taken all of count
+ val newCount = count - taken.length
+ val wrapped = Wrap(taken)
+ val newRhs = if (rhs.isEmpty) wrapped else Append(wrapped, rhs)
+ lhs match {
+ case lhsNE: NonEmpty[A] if newCount > 0 =>
+ go(Empty, newCount, lhsNE, newRhs)
+ case _ => newRhs
+ }
+ }
+ case Append(l, r) =>
+ go(if (lhs.isEmpty) l else Append(lhs, l), count, r, rhs)
+ case s @ Singleton(_) =>
+ // due to the invariant count >= 1
+ val newRhs = if (rhs.isEmpty) s else Append(s, rhs)
+ lhs match {
+ case lhsNE: NonEmpty[A] if count > 1 =>
+ go(Empty, count - 1, lhsNE, newRhs)
+ case _ => newRhs
+ }
+ }
+
+ this match {
+ case ne: NonEmpty[A] if count > 0L =>
+ go(Empty, count, ne, Empty)
+ case _ => Empty
+ }
+ }
+
/**
* Drops longest prefix of elements that satisfy a predicate.
*
@@ -210,6 +368,105 @@ sealed abstract class Chain[+A] {
go(this)
}
+ /**
+ * Drop a certain amount of items from the front of the Chain
+ */
+ final def drop(count: Long): Chain[A] = {
+ // invariant count >= 1
+ @tailrec
+ def go(count: Long, arg: NonEmpty[A], rhs: Chain[A]): Chain[A] =
+ arg match {
+ case Wrap(seq) =>
+ val dropped = if (count < Int.MaxValue) seq.drop(count.toInt) else seq.drop(Int.MaxValue)
+ val lc = dropped.lengthCompare(1)
+ if (lc < 0) {
+ // if dropped.length < 1, then it is zero
+ // we may have not dropped all of count
+ val newCount = count - seq.length
+ rhs match {
+ case rhsNE: NonEmpty[A] if newCount > 0 =>
+ // we have to keep dropping on the rhs
+ go(newCount, rhsNE, Empty)
+ case _ =>
+ // we know that count >= seq.length else we wouldn't be empty
+ // so in this case, it is exactly count == seq.length
+ rhs
+ }
+ } else {
+ // dropped is not empty
+ val wrapped = if (lc > 0) Wrap(dropped) else Singleton(dropped.head)
+ // we must be done
+ if (rhs.isEmpty) wrapped else Append(wrapped, rhs)
+ }
+ case Append(l, r) =>
+ go(count, l, if (rhs.isEmpty) r else Append(r, rhs))
+ case Singleton(_) =>
+ // due to the invariant count >= 1
+ rhs match {
+ case rhsNE: NonEmpty[A] if count > 1L =>
+ go(count - 1L, rhsNE, Empty)
+ case _ =>
+ rhs
+ }
+ }
+
+ this match {
+ case ne: NonEmpty[A] if count > 0L =>
+ go(count, ne, Empty)
+ case _ => this
+ }
+ }
+
+ /**
+ * Drop a certain amount of items from the back of the Chain
+ */
+ final def dropRight(count: Long): Chain[A] = {
+ // invariant count >= 1
+ @tailrec
+ def go(lhs: Chain[A], count: Long, arg: NonEmpty[A]): Chain[A] =
+ arg match {
+ case Wrap(seq) =>
+ val dropped = if (count < Int.MaxValue) seq.dropRight(count.toInt) else seq.dropRight(Int.MaxValue)
+ val lc = dropped.lengthCompare(1)
+ if (lc < 0) {
+ // if dropped.length < 1, then it is zero
+ // we may have not dropped all of count
+ val newCount = count - seq.length
+ lhs match {
+ case lhsNE: NonEmpty[A] if newCount > 0L =>
+ // we have to keep dropping on the lhs
+ go(Empty, newCount, lhsNE)
+ case _ =>
+ // we know that count >= seq.length else we wouldn't be empty
+ // so in this case, it is exactly count == seq.length
+ lhs
+ }
+ } else {
+ // we must be done
+ // note: dropped.nonEmpty
+ val wrapped = if (lc > 0) Wrap(dropped) else Singleton(dropped.head)
+ if (lhs.isEmpty) wrapped else Append(lhs, wrapped)
+ }
+ case Append(l, r) =>
+ go(if (lhs.isEmpty) l else Append(lhs, l), count, r)
+ case Singleton(_) =>
+ // due to the invariant count >= 1
+ lhs match {
+ case lhsNE: NonEmpty[A] if count > 1L =>
+ go(Empty, count - 1L, lhsNE)
+ case _ =>
+ lhs
+ }
+ }
+
+ this match {
+ case ne: NonEmpty[A] if count > 0L =>
+ go(Empty, count, ne)
+ case _ =>
+ this
+ }
+ }
+
/**
* Folds over the elements from right to left using the supplied initial value and function.
*/
@@ -357,7 +614,7 @@ sealed abstract class Chain[+A] {
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.{Chain, NonEmptyChain}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val chain = Chain(12, -2, 3, -5)
* scala> val expectedResult = SortedMap(false -> NonEmptyChain(-2, -5), true -> NonEmptyChain(12, 3))
* scala> val result = chain.groupBy(_ >= 0)
@@ -377,7 +634,7 @@ sealed abstract class Chain[+A] {
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.{Chain, NonEmptyChain}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val chain = Chain(12, -2, 3, -5)
* scala> val expectedResult = SortedMap(false -> NonEmptyChain("-2", "-5"), true -> NonEmptyChain("12", "3"))
* scala> val result = chain.groupMap(_ >= 0)(_.toString)
@@ -412,7 +669,7 @@ sealed abstract class Chain[+A] {
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.Chain
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val chain = Chain("Hello", "World", "Goodbye", "World")
* scala> val expectedResult = SortedMap("goodbye" -> 1, "hello" -> 1, "world" -> 2)
* scala> val result = chain.groupMapReduce(_.trim.toLowerCase)(_ => 1)
@@ -434,7 +691,7 @@ sealed abstract class Chain[+A] {
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.Chain
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val chain = Chain("Hello", "World", "Goodbye", "World")
* scala> val expectedResult = SortedMap("goodbye" -> 1, "hello" -> 1, "world" -> 2)
* scala> val result = chain.groupMapReduceWith(_.trim.toLowerCase)(_ => 1)(_ + _)
@@ -463,8 +720,38 @@ sealed abstract class Chain[+A] {
/**
* Reverses this `Chain`
*/
- def reverse: Chain[A] =
- fromSeq(reverseIterator.toVector)
+ def reverse: Chain[A] = {
+ @annotation.tailrec
+ def loop[B <: A](h: Chain.NonEmpty[B], tail: List[Chain.NonEmpty[B]], acc: Chain[A]): Chain[A] =
+ h match {
+ case Append(l, r) => loop(l, r :: tail, acc)
+ case sing @ Singleton(_) =>
+ val nextAcc = sing.concat(acc)
+ tail match {
+ case h1 :: t1 =>
+ loop(h1, t1, nextAcc)
+ case _ =>
+ nextAcc
+ }
+ case Wrap(seq) =>
+ val nextAcc = Wrap(seq.reverse).concat(acc)
+ tail match {
+ case h1 :: t1 =>
+ loop(h1, t1, nextAcc)
+ case _ =>
+ nextAcc
+ }
+ }
+
+ this match {
+ case Append(l, r) =>
+ loop(l, r :: Nil, Empty)
+ case Wrap(seq) => Wrap(seq.reverse)
+ case _ =>
+ // Empty | Singleton(_)
+ this
+ }
+ }
/**
* Yields to Some(a, Chain[A]) with `a` removed where `f` holds for the first time,
@@ -547,10 +834,35 @@ sealed abstract class Chain[+A] {
* Returns the number of elements in this structure
*/
final def length: Long = {
- val iter = iterator
- var i: Long = 0
- while (iter.hasNext) { i += 1; iter.next(); }
- i
+ // This is an optimized (unboxed) implementation
+ // of the same code as foldLeft
+ @annotation.tailrec
+ def loop(head: Chain.NonEmpty[A], tail: List[Chain.NonEmpty[A]], acc: Long): Long =
+ head match {
+ case Append(l, r) => loop(l, r :: tail, acc)
+ case Singleton(_) =>
+ val nextAcc = acc + 1L
+ tail match {
+ case h1 :: t1 =>
+ loop(h1, t1, nextAcc)
+ case _ =>
+ nextAcc
+ }
+ case Wrap(seq) =>
+ val nextAcc = acc + seq.length.toLong
+ tail match {
+ case h1 :: t1 =>
+ loop(h1, t1, nextAcc)
+ case _ =>
+ nextAcc
+ }
+ }
+
+ this match {
+ case ne: Chain.NonEmpty[A] =>
+ loop(ne, Nil, 0L)
+ case _ => 0L
+ }
}
/**
@@ -558,6 +870,70 @@ sealed abstract class Chain[+A] {
*/
final def size: Long = length
+ /**
+ * Compares the length of this chain to a test value.
+ *
+ * The method does not call `length` directly; its running time
+ * is `O(length min len)` instead of `O(length)`.
+ *
+ * @param len the test value that gets compared with the length.
+ * @return a negative value if `this.length < len`,
+ * zero if `this.length == len` or
+ * a positive value if `this.length > len`.
+ * @note an adapted version of
+ [[https://github.com/scala/scala/blob/v2.13.8/src/library/scala/collection/Iterable.scala#L272-L288 Iterable#sizeCompare]]
+ from Scala Library v2.13.10 is used in a part of the implementation.
+ *
+ * {{{
+ * scala> import cats.data.Chain
+ * scala> val chain = Chain(1, 2, 3)
+ * scala> val isLessThan4 = chain.lengthCompare(4) < 0
+ * scala> val isEqualTo3 = chain.lengthCompare(3) == 0
+ * scala> val isGreaterThan2 = chain.lengthCompare(2) > 0
+ * scala> isLessThan4 && isEqualTo3 && isGreaterThan2
+ * res0: Boolean = true
+ * }}}
+ */
+ final def lengthCompare(len: Long): Int = {
+ // This is an optimized (unboxed) implementation
+ // of the same code as foldLeft
+ @annotation.tailrec
+ def loop(head: Chain.NonEmpty[A], tail: List[Chain.NonEmpty[A]], len: Long): Int =
+ if (len <= 0L) 1 // head is nonempty
+ else
+ head match {
+ case Append(l, r) => loop(l, r :: tail, len)
+ case Singleton(_) =>
+ tail match {
+ case h1 :: t1 =>
+ loop(h1, t1, len - 1L)
+ case _ =>
+ java.lang.Long.compare(1L, len)
+ }
+ case Wrap(seq) =>
+ val c =
+ if (len <= Int.MaxValue) seq.lengthCompare(len.toInt)
+ else -1
+ tail match {
+ case h1 :: t1 =>
+ if (c >= 0) 1 // there is definitely more in tail
+ else loop(h1, t1, len - seq.length)
+ case _ => c
+ }
+ }
+
+ this match {
+ case ne: Chain.NonEmpty[A] =>
+ loop(ne, Nil, len)
+ case _ => java.lang.Long.compare(0L, len)
+ }
+ }
+
+ /**
+ * Alias for lengthCompare
+ */
+ final def sizeCompare(size: Long): Int = lengthCompare(size)
+
/**
* Converts to a list.
*/
@@ -601,19 +977,59 @@ sealed abstract class Chain[+A] {
/**
* Remove duplicates. Duplicates are checked using `Order[_]` instance.
+ *
+ * Example:
+ * {{{
+ * scala> import cats.data.Chain
+ * scala> val chain = Chain(1, 2, 2, 3)
+ * scala> chain.distinct
+ * res0: cats.data.Chain[Int] = Chain(1, 2, 3)
+ * }}}
*/
def distinct[AA >: A](implicit O: Order[AA]): Chain[AA] = {
- implicit val ord: Ordering[AA] = O.toOrdering
-
- var alreadyIn = TreeSet.empty[AA]
+ if (isEmptyOrSingleton) this
+ else {
+ implicit val ord: Ordering[AA] = O.toOrdering
+
+ val bldr = Vector.newBuilder[AA]
+ val seen = mutable.TreeSet.empty[AA]
+ val it = iterator
+ while (it.hasNext) {
+ val next = it.next()
+ if (seen.add(next))
+ bldr += next
+ }
+ // Result can contain a single element only.
+ Chain.fromSeq(bldr.result())
+ }
+ }
- foldLeft(Chain.empty[AA]) { (elementsSoFar, b) =>
- if (alreadyIn.contains(b)) {
- elementsSoFar
- } else {
- alreadyIn += b
- elementsSoFar :+ b
+ /**
+ * Remove duplicates by a predicate. Duplicates are checked using `Order[_]` instance.
+ *
+ * Example:
+ * {{{
+ * scala> import cats.data.Chain
+ * scala> val chain = Chain(1, 2, 3, 4)
+ * scala> chain.distinctBy(_ / 2)
+ * res0: cats.data.Chain[Int] = Chain(1, 2, 4)
+ * }}}
+ */
+ def distinctBy[B](f: A => B)(implicit O: Order[B]): Chain[A] = {
+ if (isEmptyOrSingleton) this
+ else {
+ implicit val ord: Ordering[B] = O.toOrdering
+
+ val bldr = Vector.newBuilder[A]
+ val seen = mutable.TreeSet.empty[B]
+ val it = iterator
+ while (it.hasNext) {
+ val next = it.next()
+ if (seen.add(f(next)))
+ bldr += next
}
+ // Result can contain a single element only.
+ Chain.fromSeq(bldr.result())
}
}
@@ -631,13 +1047,15 @@ sealed abstract class Chain[+A] {
builder.result()
}
- def hash[AA >: A](implicit hashA: Hash[AA]): Int = StaticMethods.orderedHash((this: Chain[AA]).iterator)
+ def hash[AA >: A](implicit hashA: Hash[AA]): Int =
+ KernelStaticMethods.orderedHash((this: Chain[AA]).iterator)
- override def toString: String = show(Show.show[A](_.toString))
+ override def toString: String =
+ show(Show.fromToString)
override def equals(o: Any): Boolean =
o match {
- case thatChain: Chain[_] =>
+ case thatChain: Chain[?] =>
(this: Chain[Any]).===(thatChain: Chain[Any])(Eq.fromUniversalEquals[Any])
case _ => false
}
@@ -663,24 +1081,29 @@ sealed abstract class Chain[+A] {
final def sortBy[B](f: A => B)(implicit B: Order[B]): Chain[A] =
this match {
- case Singleton(_) => this
case Append(_, _) => Wrap(toVector.sortBy(f)(B.toOrdering))
case Wrap(seq) => Wrap(seq.sortBy(f)(B.toOrdering))
- case _ => this
+ case _ =>
+ // Empty | Singleton(_)
+ this
}
final def sorted[AA >: A](implicit AA: Order[AA]): Chain[AA] =
this match {
- case Singleton(_) => this
case Append(_, _) => Wrap(toVector.sorted(AA.toOrdering))
case Wrap(seq) => Wrap(seq.sorted(AA.toOrdering))
- case _ => this
+ case _ =>
+ // Empty | Singleton(_)
+ this
}
}
-object Chain extends ChainInstances {
+@suppressUnusedImportWarningForScalaVersionSpecific
+object Chain extends ChainInstances with ChainCompanionCompat {
- private val sentinel: Function1[Any, Any] = new scala.runtime.AbstractFunction1[Any, Any] { def apply(a: Any) = this }
+ private val sentinel: Function1[Any, Any] = new scala.runtime.AbstractFunction1[Any, Any] {
+ def apply(a: Any): Any = this
+ }
sealed abstract private[data] class NonEmpty[A] extends Chain[A]
@@ -709,9 +1132,10 @@ object Chain extends ChainInstances {
* if the length is one, fromSeq returns Singleton
*
* The only places we create Wrap is in fromSeq and in methods that preserve
- * length: zipWithIndex, map, sort
+ * length: zipWithIndex, map, sort. Additionally, in drop/dropRight we carefully
+ * preserve this invariant.
*/
- final private[data] case class Wrap[A](seq: Seq[A]) extends NonEmpty[A]
+ final private[data] case class Wrap[A](seq: immutable.Seq[A]) extends NonEmpty[A]
def unapplySeq[A](chain: Chain[A]): Option[Seq[A]] =
Some(chain.toList)
@@ -757,14 +1181,6 @@ object Chain extends ChainInstances {
def fromOption[A](o: Option[A]): Chain[A] =
o.fold(Chain.empty[A])(Chain.one)
- /**
- * Creates a Chain from the specified sequence.
- */
- def fromSeq[A](s: Seq[A]): Chain[A] =
- if (s.isEmpty) nil
- else if (s.lengthCompare(1) == 0) one(s.head)
- else Wrap(s)
-
/**
* Creates a Chain from the specified elements.
*/
@@ -772,7 +1188,7 @@ object Chain extends ChainInstances {
fromSeq(as)
def traverseViaChain[G[_], A, B](
- as: ImIndexedSeq[A]
+ as: immutable.IndexedSeq[A]
)(f: A => G[B])(implicit G: Applicative[G]): G[Chain[B]] =
if (as.isEmpty) G.pure(Chain.nil)
else {
@@ -818,7 +1234,7 @@ object Chain extends ChainInstances {
}
def traverseFilterViaChain[G[_], A, B](
- as: ImIndexedSeq[A]
+ as: immutable.IndexedSeq[A]
)(f: A => G[Option[B]])(implicit G: Applicative[G]): G[Chain[B]] =
if (as.isEmpty) G.pure(Chain.nil)
else {
@@ -977,14 +1393,10 @@ object Chain extends ChainInstances {
}
sealed abstract private[data] class ChainInstances extends ChainInstances1 {
- implicit def catsDataMonoidForChain[A]: Monoid[Chain[A]] =
- new Monoid[Chain[A]] {
- def empty: Chain[A] = Chain.nil
- def combine(c: Chain[A], c2: Chain[A]): Chain[A] = Chain.concat(c, c2)
- }
+ implicit def catsDataMonoidForChain[A]: Monoid[Chain[A]] = theMonoid.asInstanceOf[Monoid[Chain[A]]]
implicit val catsDataInstancesForChain
- : Traverse[Chain] with Alternative[Chain] with Monad[Chain] with CoflatMap[Chain] with Align[Chain] =
+ : Traverse[Chain] & Alternative[Chain] & Monad[Chain] & CoflatMap[Chain] & Align[Chain] =
new Traverse[Chain] with Alternative[Chain] with Monad[Chain] with CoflatMap[Chain] with Align[Chain] {
def foldLeft[A, B](fa: Chain[A], b: B)(f: (B, A) => B): B =
fa.foldLeft(b)(f)
@@ -998,6 +1410,9 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 {
Eval.defer(loop(fa))
}
+ override def foldMap[A, B](fa: Chain[A])(f: A => B)(implicit B: Monoid[B]): B =
+ B.combineAll(fa.iterator.map(f))
+
override def map[A, B](fa: Chain[A])(f: A => B): Chain[B] = fa.map(f)
override def toList[A](fa: Chain[A]): List[A] = fa.toList
override def isEmpty[A](fa: Chain[A]): Boolean = fa.isEmpty
@@ -1021,14 +1436,70 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 {
def traverse[G[_], A, B](fa: Chain[A])(f: A => G[B])(implicit G: Applicative[G]): G[Chain[B]] =
if (fa.isEmpty) G.pure(Chain.nil)
else
- traverseViaChain {
- val as = collection.mutable.ArrayBuffer[A]()
- as ++= fa.iterator
- StaticMethods.wrapMutableIndexedSeq(as)
- }(f)
+ G match {
+ case x: StackSafeMonad[G] =>
+ Traverse.traverseDirectly(fa.iterator)(f)(x)
+ case _ =>
+ traverseViaChain {
+ val as = collection.mutable.ArrayBuffer[A]()
+ as ++= fa.iterator
+ KernelStaticMethods.wrapMutableIndexedSeq(as)
+ }(f)
+ }
+
+ override def traverseVoid[G[_], A, B](fa: Chain[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] =
+ G match {
+ case x: StackSafeMonad[G] => Traverse.traverseVoidDirectly(fa.iterator)(f)(x)
+ case _ =>
+ @tailrec
+ def go(fa: NonEmpty[A], rhs: Chain[A], acc: G[Unit]): G[Unit] =
+ fa match {
+ case Append(l, r) =>
+ go(l, if (rhs.isEmpty) r else Append(r, rhs), acc)
+ case Wrap(as) =>
+ val va = Foldable[collection.immutable.Seq].traverseVoid(as)(f)
+ val acc1 = G.productL(acc)(va)
+ rhs match {
+ case Empty => acc1
+ case ne: NonEmpty[A] =>
+ go(ne, Empty, acc1)
+ }
+ case Singleton(a) =>
+ val acc1 = G.productL(acc)(f(a))
+ rhs match {
+ case Empty => acc1
+ case ne: NonEmpty[A] =>
+ go(ne, Empty, acc1)
+ }
+ }
+
+ fa match {
+ case Empty => G.unit
+ case ne: NonEmpty[A] =>
+ go(ne, Empty, G.unit)
+ }
+ }
+
+ final override def toIterable[A](fa: Chain[A]): Iterable[A] = new scala.collection.AbstractIterable[A] {
+ final override def iterator: Iterator[A] =
+ fa.iterator
+ }
+
+ override def mapAccumulate[S, A, B](init: S, fa: Chain[A])(f: (S, A) => (S, B)): (S, Chain[B]) =
+ StaticMethods.mapAccumulateFromStrictFunctor(init, fa, f)(this)
+
+ override def mapWithIndex[A, B](fa: Chain[A])(f: (A, Int) => B): Chain[B] =
+ StaticMethods.mapWithIndexFromStrictFunctor(fa, f)(this)
+
+ override def mapWithLongIndex[A, B](fa: Chain[A])(f: (A, Long) => B): Chain[B] =
+ StaticMethods.mapWithLongIndexFromStrictFunctor(fa, f)(this)
+
+ override def zipWithIndex[A](fa: Chain[A]): Chain[(A, Int)] =
+ fa.zipWithIndex
def empty[A]: Chain[A] = Chain.nil
def combineK[A](c: Chain[A], c2: Chain[A]): Chain[A] = Chain.concat(c, c2)
+ override def fromIterableOnce[A](xs: IterableOnce[A]): Chain[A] = Chain.fromIterableOnce(xs)
def pure[A](a: A): Chain[A] = Chain.one(a)
def flatMap[A, B](fa: Chain[A])(f: A => Chain[B]): Chain[B] =
fa.flatMap(f)
@@ -1084,8 +1555,7 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 {
}
}
- implicit def catsDataShowForChain[A](implicit A: Show[A]): Show[Chain[A]] =
- Show.show[Chain[A]](_.show)
+ implicit def catsDataShowForChain[A: Show]: Show[Chain[A]] = _.show
implicit def catsDataOrderForChain[A](implicit A0: Order[A]): Order[Chain[A]] =
new Order[Chain[A]] with ChainPartialOrder[A] {
@@ -1107,7 +1577,7 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 {
}
implicit val catsDataTraverseFilterForChain: TraverseFilter[Chain] = new TraverseFilter[Chain] {
- def traverse: Traverse[Chain] = Chain.catsDataInstancesForChain
+ def traverse: Traverse[Chain] & Alternative[Chain] = Chain.catsDataInstancesForChain
override def filter[A](fa: Chain[A])(f: A => Boolean): Chain[A] = fa.filter(f)
@@ -1122,11 +1592,16 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 {
def traverseFilter[G[_], A, B](fa: Chain[A])(f: A => G[Option[B]])(implicit G: Applicative[G]): G[Chain[B]] =
if (fa.isEmpty) G.pure(Chain.nil)
else
- traverseFilterViaChain {
- val as = collection.mutable.ArrayBuffer[A]()
- as ++= fa.iterator
- StaticMethods.wrapMutableIndexedSeq(as)
- }(f)
+ G match {
+ case x: StackSafeMonad[G] =>
+ TraverseFilter.traverseFilterDirectly(fa.iterator)(f)(x)
+ case _ =>
+ traverseFilterViaChain {
+ val as = collection.mutable.ArrayBuffer[A]()
+ as ++= fa.iterator
+ KernelStaticMethods.wrapMutableIndexedSeq(as)
+ }(f)
+ }
override def filterA[G[_], A](fa: Chain[A])(f: A => G[Boolean])(implicit G: Applicative[G]): G[Chain[A]] =
traverse
@@ -1137,6 +1612,12 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 {
}
+ private[this] val theMonoid: Monoid[Chain[Any]] = new Monoid[Chain[Any]] {
+ def empty: Chain[Any] = Chain.nil
+
+ def combine(c: Chain[Any], c2: Chain[Any]): Chain[Any] = Chain.concat(c, c2)
+ }
+
}
sealed abstract private[data] class ChainInstances1 extends ChainInstances2 {
diff --git a/core/src/main/scala/cats/data/Cokleisli.scala b/core/src/main/scala/cats/data/Cokleisli.scala
index be1c898d36..06f1fb8ccd 100644
--- a/core/src/main/scala/cats/data/Cokleisli.scala
+++ b/core/src/main/scala/cats/data/Cokleisli.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala/cats/data/Const.scala b/core/src/main/scala/cats/data/Const.scala
index 6cf593457e..61c436431f 100644
--- a/core/src/main/scala/cats/data/Const.scala
+++ b/core/src/main/scala/cats/data/Const.scala
@@ -1,8 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
import cats.kernel.{CommutativeMonoid, CommutativeSemigroup, LowerBounded, UpperBounded}
+import scala.annotation.nowarn
+
/**
* [[Const]] is a phantom type, it does not contain a value of its second type parameter `B`
* [[Const]] can be seen as a type level version of `Function.const[A, B]: A => B => A`
@@ -18,6 +41,7 @@ final case class Const[A, B](getConst: A) {
def combine(that: Const[A, B])(implicit A: Semigroup[A]): Const[A, B] =
Const(A.combine(getConst, that.getConst))
+ @nowarn("cat=unused")
def traverse[F[_], C](f: B => F[C])(implicit F: Applicative[F]): F[Const[A, C]] =
F.pure(retag[C])
@@ -30,6 +54,9 @@ final case class Const[A, B](getConst: A) {
def compare(that: Const[A, B])(implicit A: Order[A]): Int =
A.compare(getConst, that.getConst)
+ def hash(implicit A: Hash[A]): Int =
+ Const(A.hash(getConst)).hashCode()
+
def show(implicit A: Show[A]): String =
s"Const(${A.show(getConst)})"
}
@@ -69,26 +96,21 @@ sealed abstract private[data] class ConstInstances extends ConstInstances0 {
override def minBound: Const[A, B] = Const(A.minBound)
}
- implicit def catsDataOrderForConst[A: Order, B]: Order[Const[A, B]] =
- new Order[Const[A, B]] {
- def compare(x: Const[A, B], y: Const[A, B]): Int =
- x.compare(y)
- }
+ implicit def catsDataOrderForConst[A: Order, B]: Order[Const[A, B]] = _ compare _
+
+ implicit def catsDataPartialOrderForConst[A: PartialOrder, B]: PartialOrder[Const[A, B]] = _ partialCompare _
implicit def catsDataAlignForConst[A: Semigroup]: Align[Const[A, *]] =
new Align[Const[A, *]] {
def align[B, C](fa: Const[A, B], fb: Const[A, C]): Const[A, Ior[B, C]] =
Const(Semigroup[A].combine(fa.getConst, fb.getConst))
- def functor: Functor[Const[A, *]] = catsDataFunctorForConst
+ def functor: Functor[Const[A, *]] = catsDataTraverseForConst
}
- implicit def catsDataShowForConst[A: Show, B]: Show[Const[A, B]] =
- new Show[Const[A, B]] {
- def show(f: Const[A, B]): String = f.show
- }
+ implicit def catsDataShowForConst[A: Show, B]: Show[Const[A, B]] = _.show
implicit def catsDataTraverseForConst[C]: Traverse[Const[C, *]] =
- new Traverse[Const[C, *]] {
+ new Traverse[Const[C, *]] with ConstFunctor[C] {
def foldLeft[A, B](fa: Const[C, A], b: B)(f: (B, A) => B): B = b
def foldRight[A, B](fa: Const[C, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = lb
@@ -99,27 +121,30 @@ sealed abstract private[data] class ConstInstances extends ConstInstances0 {
def traverse[G[_]: Applicative, A, B](fa: Const[C, A])(f: A => G[B]): G[Const[C, B]] =
fa.traverse(f)
+
+ override def mapAccumulate[S, A, B](init: S, fa: Const[C, A])(f: (S, A) => (S, B)): (S, Const[C, B]) =
+ (init, fa.retag)
}
implicit def catsDataTraverseFilterForConst[C]: TraverseFilter[Const[C, *]] =
new TraverseFilter[Const[C, *]] {
- override def mapFilter[A, B](fa: Const[C, A])(f: (A) => Option[B]): Const[C, B] = fa.retag
+ override def mapFilter[A, B](fa: Const[C, A])(f: A => Option[B]): Const[C, B] = fa.retag
override def collect[A, B](fa: Const[C, A])(f: PartialFunction[A, B]): Const[C, B] = fa.retag
override def flattenOption[A](fa: Const[C, Option[A]]): Const[C, A] = fa.retag
- override def filter[A](fa: Const[C, A])(f: (A) => Boolean): Const[C, A] = fa.retag
+ override def filter[A](fa: Const[C, A])(f: A => Boolean): Const[C, A] = fa.retag
override def filterNot[A](fa: Const[C, A])(f: A => Boolean): Const[C, A] = fa.retag
def traverseFilter[G[_], A, B](
fa: Const[C, A]
- )(f: (A) => G[Option[B]])(implicit G: Applicative[G]): G[Const[C, B]] =
+ )(f: A => G[Option[B]])(implicit G: Applicative[G]): G[Const[C, B]] =
G.pure(fa.retag[B])
- override def filterA[G[_], A](fa: Const[C, A])(f: (A) => G[Boolean])(implicit G: Applicative[G]): G[Const[C, A]] =
+ override def filterA[G[_], A](fa: Const[C, A])(f: A => G[Boolean])(implicit G: Applicative[G]): G[Const[C, A]] =
G.pure(fa)
val traverse: Traverse[Const[C, *]] = Const.catsDataTraverseForConst[C]
@@ -134,6 +159,8 @@ sealed abstract private[data] class ConstInstances extends ConstInstances0 {
x.combine(y)
}
+ implicit def catsDataSemigroupForConst[A: Semigroup, B]: Semigroup[Const[A, B]] = _ combine _
+
implicit val catsDataBifoldableForConst: Bifoldable[Const] =
new Bifoldable[Const] {
def bifoldLeft[A, B, C](fab: Const[A, B], c: C)(f: (C, A) => C, g: (C, B) => C): C =
@@ -144,10 +171,26 @@ sealed abstract private[data] class ConstInstances extends ConstInstances0 {
): Eval[C] =
f(fab.getConst, c)
}
+
+ implicit def catsDataMonoidKForConst[C: Monoid]: MonoidK[Const[C, *]] = new MonoidK[Const[C, *]] {
+ override def empty[A]: Const[C, A] = Const.empty
+ override def combineK[A](x: Const[C, A], y: Const[C, A]): Const[C, A] = x.combine(y)
+ }
+
+ implicit def catsDataSemigroupKForConst[C: Semigroup]: SemigroupK[Const[C, *]] = new SemigroupK[Const[C, *]] {
+ override def combineK[A](x: Const[C, A], y: Const[C, A]): Const[C, A] = x.combine(y)
+ }
}
sealed abstract private[data] class ConstInstances0 extends ConstInstances1 {
+ implicit def catsDataEqForConst[A: Eq, B]: Eq[Const[A, B]] = _ === _
+
+ implicit def catsDataHashForConst[A: Hash, B]: Hash[Const[A, B]] = new Hash[Const[A, B]] {
+ override def hash(x: Const[A, B]): Int = x.hash
+ override def eqv(x: Const[A, B], y: Const[A, B]): Boolean = x === y
+ }
+
implicit def catsDataContravariantMonoidalForConst[D: Monoid]: ContravariantMonoidal[Const[D, *]] =
new ContravariantMonoidal[Const[D, *]] {
override def unit = Const.empty[D, Unit]
@@ -157,58 +200,51 @@ sealed abstract private[data] class ConstInstances0 extends ConstInstances1 {
fa.retag[(A, B)].combine(fb.retag[(A, B)])
}
- implicit def catsDataCommutativeApplicativeForConst[C](implicit
- C: CommutativeMonoid[C]
- ): CommutativeApplicative[Const[C, *]] =
- new ConstApplicative[C] with CommutativeApplicative[Const[C, *]] { val C0: CommutativeMonoid[C] = C }
+ implicit def catsDataContravariantSemigroupalForConst[D: Semigroup]: ContravariantSemigroupal[Const[D, *]] =
+ new ContravariantSemigroupal[Const[D, *]] {
+ override def contramap[A, B](fa: Const[D, A])(f: B => A): Const[D, B] =
+ fa.retag[B]
+ override def product[A, B](fa: Const[D, A], fb: Const[D, B]): Const[D, (A, B)] =
+ fa.retag[(A, B)].combine(fb.retag[(A, B)])
+ }
}
sealed abstract private[data] class ConstInstances1 extends ConstInstances2 {
+ implicit def catsDataCommutativeApplicativeForConst[C](implicit
+ C: CommutativeMonoid[C]
+ ): CommutativeApplicative[Const[C, *]] =
+ new ConstApplicative[C] with CommutativeApplicative[Const[C, *]] {
+ val C0: CommutativeMonoid[C] = C
+ }
+
implicit def catsDataCommutativeApplyForConst[C](implicit C: CommutativeSemigroup[C]): CommutativeApply[Const[C, *]] =
new ConstApply[C] with CommutativeApply[Const[C, *]] { val C0: CommutativeSemigroup[C] = C }
}
sealed abstract private[data] class ConstInstances2 extends ConstInstances3 {
- implicit def catsDataSemigroupForConst[A: Semigroup, B]: Semigroup[Const[A, B]] =
- new Semigroup[Const[A, B]] {
- def combine(x: Const[A, B], y: Const[A, B]): Const[A, B] = x.combine(y)
- }
-
- implicit def catsDataPartialOrderForConst[A: PartialOrder, B]: PartialOrder[Const[A, B]] =
- new PartialOrder[Const[A, B]] {
- def partialCompare(x: Const[A, B], y: Const[A, B]): Double =
- x.partialCompare(y)
- }
-
implicit def catsDataApplicativeForConst[C](implicit C: Monoid[C]): Applicative[Const[C, *]] =
new ConstApplicative[C] { val C0: Monoid[C] = C }
-}
-
-sealed abstract private[data] class ConstInstances3 extends ConstInstances4 {
-
- implicit def catsDataEqForConst[A: Eq, B]: Eq[Const[A, B]] =
- new Eq[Const[A, B]] {
- def eqv(x: Const[A, B], y: Const[A, B]): Boolean =
- x === y
- }
implicit def catsDataApplyForConst[C](implicit C: Semigroup[C]): Apply[Const[C, *]] =
new ConstApply[C] { val C0: Semigroup[C] = C }
}
-sealed abstract private[data] class ConstInstances4 {
+sealed abstract private[data] class ConstInstances3 extends ConstInstances4 {
- implicit def catsDataFunctorForConst[C]: Functor[Const[C, *]] =
+ @deprecated("Use catsDataTraverseForConst instead", "2.10.0")
+ def catsDataFunctorForConst[C]: Functor[Const[C, *]] =
new ConstFunctor[C] {}
implicit def catsDataContravariantForConst[C]: Contravariant[Const[C, *]] =
new ConstContravariant[C] {}
}
+sealed abstract private[data] class ConstInstances4
+
sealed private[data] trait ConstFunctor[C] extends Functor[Const[C, *]] {
- def map[A, B](fa: Const[C, A])(f: A => B): Const[C, B] =
+ final override def map[A, B](fa: Const[C, A])(f: A => B): Const[C, B] =
fa.retag[B]
}
@@ -228,7 +264,7 @@ sealed private[data] trait ConstApply[C] extends ConstFunctor[C] with Apply[Cons
fa.retag[(A, B)].combine(fb.retag[(A, B)])
}
-sealed private[data] trait ConstApplicative[C] extends ConstApply[C] with Applicative[Const[C, *]] {
+sealed private[data] trait ConstApplicative[C] extends Applicative[Const[C, *]] with ConstApply[C] {
implicit def C0: Monoid[C]
diff --git a/core/src/main/scala/cats/data/ContT.scala b/core/src/main/scala/cats/data/ContT.scala
index efbc41c54f..669aa4cbcf 100644
--- a/core/src/main/scala/cats/data/ContT.scala
+++ b/core/src/main/scala/cats/data/ContT.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -120,7 +141,7 @@ object ContT {
* _ <- ContT.callCC( (k: Unit => ContT[IO, Unit, Unit]) =>
* ContT.liftF(IO.println("this will print first")) >>
* k(()) >>
- * ContT.liftF(IO.println("this will NOT print as we short-circuit to the contination"))
+ * ContT.liftF(IO.println("this will NOT print as we short-circuit to the continuation"))
* )
* _ <- ContT.liftF(IO.println("this will print second")])
* } yield ()
diff --git a/core/src/main/scala/cats/data/EitherK.scala b/core/src/main/scala/cats/data/EitherK.scala
index e5719bb2fb..472ad42c79 100644
--- a/core/src/main/scala/cats/data/EitherK.scala
+++ b/core/src/main/scala/cats/data/EitherK.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala/cats/data/EitherT.scala b/core/src/main/scala/cats/data/EitherT.scala
index 77de49254f..491d683f77 100644
--- a/core/src/main/scala/cats/data/EitherT.scala
+++ b/core/src/main/scala/cats/data/EitherT.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -18,7 +39,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Left("456"), Right(123)))
@@ -33,7 +54,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123),Left("abc")))
@@ -46,7 +67,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List,String,Int] = EitherT[List, String,Int](List(Right(123),Left("abc")))
@@ -59,7 +80,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List,String,Int] = EitherT[List, String,Int](List(Right(123),Left("abc")))
@@ -72,7 +93,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List,String,Int] = EitherT[List, String,Int](List(Right(123),Left("abc")))
@@ -85,7 +106,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List,String,Int] = EitherT[List, String,Int](List(Right(123),Left("abc")))
@@ -98,7 +119,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List,String,Int] = EitherT[List, String,Int](List(Right(123),Left("abc")))
@@ -112,10 +133,30 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
case Right(b) => F.pure(b)
}
+ /***
+ *
+ * Like [[getOrElseF]] but accept an error `E` and raise it when the inner `Either` is `Left`
+ *
+ * Equivalent to `getOrElseF(F.raiseError(e)))`
+ *
+ * Example:
+ * {{{
+ * scala> import cats.data.EitherT
+ * scala> import cats.syntax.all._
+ * scala> import scala.util.{Success, Failure, Try}
+
+ * scala> val eitherT: EitherT[Try,String,Int] = EitherT[Try,String,Int](Success(Left("abc")))
+ * scala> eitherT.getOrRaise(new RuntimeException("ERROR!"))
+ * res0: Try[Int] = Failure(java.lang.RuntimeException: ERROR!)
+ * }}}
+ */
+ def getOrRaise[E](e: => E)(implicit F: MonadError[F, ? >: E]): F[B] =
+ getOrElseF(F.raiseError(e))
+
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val e1: EitherT[Option,String,Int] = EitherT[Option, String,Int](Some(Right(123)))
@@ -136,7 +177,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List,String,Int] =
@@ -159,7 +200,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List,String,Int] =
@@ -184,7 +225,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val e1: EitherT[Option, Unit, Int] = EitherT[Option, Unit, Int](Some(Right(123)))
@@ -207,13 +248,13 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
* res3: util.Try[String] = Failure(java.lang.Exception: sad cats)
* }}}
*/
- def rethrowT(implicit F: MonadError[F, _ >: A]): F[B] =
+ def rethrowT(implicit F: MonadError[F, ? >: A]): F[B] =
F.rethrow(value)
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
@@ -226,7 +267,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
@@ -243,7 +284,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
@@ -256,7 +297,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
@@ -269,7 +310,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val e1: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
@@ -294,7 +335,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val e1: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
@@ -319,7 +360,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
@@ -332,7 +373,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
@@ -349,7 +390,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] =
@@ -367,7 +408,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] =
@@ -446,7 +487,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
*
* scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Left("abc"), Right(123)))
@@ -472,6 +513,14 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
def leftSemiflatTap[C](f: A => F[C])(implicit F: Monad[F]): EitherT[F, A, B] =
leftSemiflatMap(a => F.as(f(a), a))
+ def biSemiflatTap[C, D](fa: A => F[C], fb: B => F[D])(implicit F: FlatMap[F]): EitherT[F, A, B] =
+ EitherT(F.flatMap(value) {
+ case l @ Left(a) =>
+ F.as(fa(a), l)
+ case r @ Right(b) =>
+ F.as(fb(b), r)
+ })
+
def compare(that: EitherT[F, A, B])(implicit o: Order[F[Either[A, B]]]): Int =
o.compare(value, that.value)
@@ -486,6 +535,11 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
)(implicit traverseF: Traverse[F], applicativeG: Applicative[G]): G[EitherT[F, A, D]] =
applicativeG.map(traverseF.traverse(value)(axb => Traverse[Either[A, *]].traverse(axb)(f)))(EitherT.apply)
+ def mapAccumulate[S, C](init: S)(f: (S, B) => (S, C))(implicit traverseF: Traverse[F]): (S, EitherT[F, A, C]) = {
+ val (snext, vnext) = traverseF.mapAccumulate(init, value)(Traverse[Either[A, *]].mapAccumulate[S, B, C](_, _)(f))
+ (snext, EitherT(vnext))
+ }
+
def foldLeft[C](c: C)(f: (C, B) => C)(implicit F: Foldable[F]): C =
F.foldLeft(value, c) {
case (c, Right(b)) => f(c, b)
@@ -506,7 +560,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
* Examples:
* {{{
* scala> import cats.data.EitherT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val l1: EitherT[Option, String, Int] = EitherT.left(Some("error 1"))
* scala> val l2: EitherT[Option, String, Int] = EitherT.left(Some("error 2"))
* scala> val r3: EitherT[Option, String, Int] = EitherT.right(Some(3))
@@ -570,7 +624,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> type Error = String
* scala> val v1: Validated[NonEmptyList[Error], Int] = Validated.invalidNel("error 1")
* scala> val v2: Validated[NonEmptyList[Error], Int] = Validated.invalidNel("error 2")
@@ -593,7 +647,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
*
* {{{
* scala> import cats.data.EitherT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val ff: EitherT[List, String, Int => String] =
* | EitherT(List(Either.right(_.toString), Either.left("error")))
* scala> val fa: EitherT[List, String, Int] =
@@ -612,7 +666,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
* Example:
* {{{
* scala> import cats.data.{EitherT, Validated}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val f: Int => String = i => (i*2).toString
* scala> val r1: EitherT[Option, String, Int => String] = EitherT.right(Some(f))
* r1: cats.data.EitherT[Option,String,Int => String] = EitherT(Some(Right()))
@@ -647,6 +701,11 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
case Left(a) => Validated.invalidNec(a)
}
)
+
+ /** Convert this `EitherT[F, A, B]` into an `IorT[F, A, B]`.
+ */
+ def toIor(implicit F: Functor[F]): IorT[F, A, B] =
+ IorT.fromEitherF(value)
}
object EitherT extends EitherTInstances {
@@ -662,7 +721,7 @@ object EitherT extends EitherTInstances {
* Creates a left version of `EitherT[F, A, B]` from a `F[A]`
* {{{
* scala> import cats.data.EitherT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> EitherT.left[Int](Option("err"))
* res0: cats.data.EitherT[Option,String,Int] = EitherT(Some(Left(err)))
* }}}
@@ -680,7 +739,7 @@ object EitherT extends EitherTInstances {
* Creates a left version of `EitherT[F, A, B]` from a `A`
* {{{
* scala> import cats.data.EitherT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> EitherT.leftT[Option, Int]("err")
* res0: cats.data.EitherT[Option,String,Int] = EitherT(Some(Left(err)))
* }}}
@@ -698,7 +757,7 @@ object EitherT extends EitherTInstances {
* Creates a right version of `EitherT[F, A, B]` from a `F[B]`
* {{{
* scala> import cats.data.EitherT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> EitherT.right[String](Option(3))
* res0: cats.data.EitherT[Option,String,Int] = EitherT(Some(Right(3)))
* }}}
@@ -716,7 +775,7 @@ object EitherT extends EitherTInstances {
* Creates a new `EitherT[F, A, B]` from a `B`
* {{{
* scala> import cats.data.EitherT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> EitherT.pure[Option, String](3)
* res0: cats.data.EitherT[Option,String,Int] = EitherT(Some(Right(3)))
* }}}
@@ -727,7 +786,7 @@ object EitherT extends EitherTInstances {
* Alias for [[pure]]
* {{{
* scala> import cats.data.EitherT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> EitherT.rightT[Option, String](3)
* res0: cats.data.EitherT[Option,String,Int] = EitherT(Some(Right(3)))
* }}}
@@ -738,7 +797,7 @@ object EitherT extends EitherTInstances {
* Alias for [[right]]
* {{{
* scala> import cats.data.EitherT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val o: Option[Int] = Some(3)
* scala> val n: Option[Int] = None
* scala> EitherT.liftF(o)
@@ -792,7 +851,7 @@ object EitherT extends EitherTInstances {
* Note: The return type is a FromEitherPartiallyApplied[F], which has an apply method
* on it, allowing you to call fromEither like this:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val t: Either[String, Int] = Either.right(3)
* scala> EitherT.fromEither[Option](t)
* res0: EitherT[Option, String, Int] = EitherT(Some(Right(3)))
@@ -814,7 +873,7 @@ object EitherT extends EitherTInstances {
* Transforms an `Option` into an `EitherT`, lifted into the specified `Applicative` and using
* the second argument if the `Option` is a `None`.
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val o: Option[Int] = None
* scala> EitherT.fromOption[List](o, "Answer not known.")
* res0: EitherT[List, String, Int] = EitherT(List(Left(Answer not known.)))
@@ -842,7 +901,7 @@ object EitherT extends EitherTInstances {
/**
* Transforms an `F[Option]` into an `EitherT`, using the second argument if the `Option` is a `None`.
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val o: Option[Int] = None
* scala> EitherT.fromOptionF(List(o), "Answer not known.")
* res0: EitherT[List, String, Int] = EitherT(List(Left(Answer not known.)))
@@ -906,10 +965,8 @@ abstract private[data] class EitherTInstances extends EitherTInstances1 {
implicit def catsDataShowForEitherT[F[_], L, R](implicit sh: Show[F[Either[L, R]]]): Show[EitherT[F, L, R]] =
Contravariant[Show].contramap(sh)(_.value)
- implicit def catsDataBifunctorForEitherT[F[_]](implicit F: Functor[F]): Bifunctor[EitherT[F, *, *]] =
- new EitherTBifunctor[F] {
- val F0: Functor[F] = F
- }
+ implicit def catsDataBitraverseForEitherT[F[_]](implicit F: Traverse[F]): Bitraverse[EitherT[F, *, *]] =
+ new EitherTBitraverse[F] { val F0 = F }
implicit def catsDataTraverseForEitherT[F[_], L](implicit FF: Traverse[F]): Traverse[EitherT[F, L, *]] =
new EitherTTraverse[F, L] with EitherTFunctor[F, L] {
@@ -960,7 +1017,6 @@ abstract private[data] class EitherTInstances extends EitherTInstances1 {
type F[x] = Nested[P.F, Validated[E, *], x]
implicit val monadM: Monad[M] = P.monad
- implicit val monadEither: Monad[Either[E, *]] = cats.instances.either.catsStdInstancesForEither
def applicative: Applicative[Nested[P.F, Validated[E, *], *]] =
cats.data.Nested.catsDataApplicativeForNested(P.applicative, Validated.catsDataApplicativeErrorForValidated)
@@ -1035,10 +1091,11 @@ abstract private[data] class EitherTInstances1 extends EitherTInstances2 {
val F0: PartialOrder[F[Either[L, R]]] = F
}
- implicit def catsDataBitraverseForEitherT[F[_]](implicit F: Traverse[F]): Bitraverse[EitherT[F, *, *]] =
- new EitherTBitraverse[F] with EitherTBifunctor[F] {
- val F0: Traverse[F] = F
- }
+ implicit def catsDataBifunctorForEitherT[F[_]](implicit F: Functor[F]): Bifunctor[EitherT[F, *, *]] =
+ new EitherTBifunctor[F] { val F0 = F }
+
+ implicit def catsDataBifoldableForEitherT[F[_]](implicit F: Foldable[F]): Bifoldable[EitherT[F, *, *]] =
+ new EitherTBifoldable[F] { val F0 = F }
implicit def catsDataMonadErrorForEitherT[F[_], L](implicit F0: Monad[F]): MonadError[EitherT[F, L, *], L] =
new EitherTMonadError[F, L] {
@@ -1056,7 +1113,6 @@ abstract private[data] class EitherTInstances1 extends EitherTInstances2 {
type F[x] = Nested[M, Validated[E, *], x]
implicit val appValidated: Applicative[Validated[E, *]] = Validated.catsDataApplicativeErrorForValidated
- implicit val monadEither: Monad[Either[E, *]] = cats.instances.either.catsStdInstancesForEither
def applicative: Applicative[Nested[M, Validated[E, *], *]] =
cats.data.Nested.catsDataApplicativeForNested[M, Validated[E, *]]
@@ -1128,14 +1184,14 @@ private[data] trait EitherTSemigroupK[F[_], L] extends SemigroupK[EitherT[F, L,
implicit val F: Monad[F]
def combineK[A](x: EitherT[F, L, A], y: EitherT[F, L, A]): EitherT[F, L, A] =
EitherT(F.flatMap(x.value) {
- case l @ Left(_) => y.value
case r @ Right(_) => F.pure(r)
+ case Left(_) => y.value
})
override def combineKEval[A](x: EitherT[F, L, A], y: Eval[EitherT[F, L, A]]): Eval[EitherT[F, L, A]] =
Eval.now(EitherT(F.flatMap(x.value) {
- case l @ Left(_) => y.value.value
case r @ Right(_) => F.pure(r: Either[L, A])
+ case Left(_) => y.value.value
}))
}
@@ -1204,6 +1260,9 @@ sealed private[data] trait EitherTTraverse[F[_], L] extends Traverse[EitherT[F,
override def traverse[G[_]: Applicative, A, B](fa: EitherT[F, L, A])(f: A => G[B]): G[EitherT[F, L, B]] =
fa.traverse(f)
+
+ override def mapAccumulate[S, A, B](init: S, fa: EitherT[F, L, A])(f: (S, A) => (S, B)): (S, EitherT[F, L, B]) =
+ fa.mapAccumulate(init)(f)
}
sealed private[data] trait EitherTBifoldable[F[_]] extends Bifoldable[EitherT[F, *, *]] {
diff --git a/core/src/main/scala/cats/data/Func.scala b/core/src/main/scala/cats/data/Func.scala
index 0961864b38..9da90104df 100644
--- a/core/src/main/scala/cats/data/Func.scala
+++ b/core/src/main/scala/cats/data/Func.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -92,7 +113,7 @@ sealed private[data] trait FuncApply[F[_], C] extends Apply[λ[α => Func[F, C,
sealed private[data] trait FuncApplicative[F[_], C] extends Applicative[λ[α => Func[F, C, α]]] with FuncApply[F, C] {
def F: Applicative[F]
def pure[A](a: A): Func[F, C, A] =
- Func.func(c => F.pure(a))
+ Func.func(Function.const(F.pure(a)))
}
/**
@@ -146,5 +167,5 @@ sealed private[data] trait AppFuncApplicative[F[_], C] extends Applicative[λ[α
override def product[A, B](fa: AppFunc[F, C, A], fb: AppFunc[F, C, B]): AppFunc[F, C, (A, B)] =
Func.appFunc[F, C, (A, B)](c => F.product(fa.run(c), fb.run(c)))(F)
def pure[A](a: A): AppFunc[F, C, A] =
- Func.appFunc[F, C, A](c => F.pure(a))(F)
+ Func.appFunc[F, C, A](Function.const(F.pure(a)))(F)
}
diff --git a/core/src/main/scala/cats/data/IdT.scala b/core/src/main/scala/cats/data/IdT.scala
index fc32760655..845ac008c7 100644
--- a/core/src/main/scala/cats/data/IdT.scala
+++ b/core/src/main/scala/cats/data/IdT.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -6,24 +27,86 @@ package data
*/
final case class IdT[F[_], A](value: F[A]) {
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.IdT
+ *
+ * scala> val idT: IdT[List, Int] = IdT(List(1, 2, 3))
+ * scala> idT.map(_ + 1)
+ * res0: IdT[List, Int] = IdT(List(2, 3, 4))
+ * }}}
+ */
def map[B](f: A => B)(implicit F: Functor[F]): IdT[F, B] =
IdT(F.map(value)(f))
/**
* Modify the context `F` using transformation `f`.
+ *
+ * Example:
+ * {{{
+ * scala> import cats.~>
+ * scala> import cats.data.IdT
+ *
+ * scala> val vectorToList: Vector ~> List = new ~>[Vector, List] { override def apply[A](v: Vector[A]): List[A] = v.toList }
+ * scala> val idT: IdT[Vector, Int] = IdT(Vector(1, 2, 3))
+ * scala> idT.mapK[List](vectorToList)
+ * res0: IdT[List, Int] = IdT(List(1, 2, 3))
+ * }}}
*/
def mapK[G[_]](f: F ~> G): IdT[G, A] =
IdT[G, A](f(value))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.IdT
+ *
+ * scala> val idT: IdT[List, Int] = IdT(List(1, 2, 3))
+ * scala> idT.flatMap(x => IdT(List(x + 1)))
+ * res0: IdT[List, Int] = IdT(List(2, 3, 4))
+ * }}}
+ */
def flatMap[B](f: A => IdT[F, B])(implicit F: FlatMap[F]): IdT[F, B] =
IdT(F.flatMap(value)(a => f(a).value))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.IdT
+ *
+ * scala> val idT: IdT[List, Int] = IdT(List(1, 2, 3))
+ * scala> idT.flatMapF(x => List(Option(x).filter(_ % 2 == 0)))
+ * res0: IdT[List, Option[Int]] = IdT(List(None, Some(2), None))
+ * }}}
+ */
def flatMapF[B](f: A => F[B])(implicit F: FlatMap[F]): IdT[F, B] =
IdT(F.flatMap(value)(f))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.IdT
+ *
+ * scala> val idT: IdT[List, Int] = IdT(List(1, 2, 3))
+ * scala> idT.foldLeft(0)((acc, x) => acc + x)
+ * res0: Int = 6
+ * }}}
+ */
def foldLeft[B](b: B)(f: (B, A) => B)(implicit F: Foldable[F]): B =
F.foldLeft(value, b)(f)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.IdT
+ * scala> import cats.Eval
+ *
+ * scala> val idT: IdT[List, Int] = IdT(List(1, 2, 3))
+ * scala> idT.foldRight(Eval.Zero)((x, acc) => Eval.later(x + acc.value)).value
+ * res0: Int = 6
+ * }}}
+ */
def foldRight[B](lb: Eval[B])(f: (A, Eval[B]) => Eval[B])(implicit F: Foldable[F]): Eval[B] =
F.foldRight(value, lb)(f)
@@ -33,6 +116,16 @@ final case class IdT[F[_], A](value: F[A]) {
def reduceRightTo[B](f: A => B)(g: (A, Eval[B]) => Eval[B])(implicit F: Reducible[F]): Eval[B] =
F.reduceRightTo(value)(f)(g)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.IdT
+ *
+ * scala> val idT: IdT[List, Int] = IdT(List(1, 2, 3))
+ * scala> idT.traverse[Option, Int](x => Option(x + 1))
+ * res0: Option[IdT[List, Int]] = Some(IdT(List(2, 3, 4)))
+ * }}}
+ */
def traverse[G[_], B](f: A => G[B])(implicit F: Traverse[F], G: Applicative[G]): G[IdT[F, B]] =
G.map(F.traverse(value)(f))(IdT(_))
@@ -120,6 +213,11 @@ sealed private[data] trait IdTTraverse[F[_]] extends Traverse[IdT[F, *]] with Id
def traverse[G[_]: Applicative, A, B](fa: IdT[F, A])(f: A => G[B]): G[IdT[F, B]] =
fa.traverse(f)
+
+ override def mapAccumulate[S, A, B](init: S, fa: IdT[F, A])(f: (S, A) => (S, B)): (S, IdT[F, B]) = {
+ val (snext, fb) = F0.mapAccumulate(init, fa.value)(f)
+ (snext, IdT(fb))
+ }
}
sealed private[data] trait IdTNonEmptyTraverse[F[_]]
diff --git a/core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala b/core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala
index 2946310fe9..b766600431 100644
--- a/core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala
+++ b/core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -27,7 +48,7 @@ final class IndexedReaderWriterStateT[F[_], E, L, SA, SB, A](val runF: F[(E, SA)
* Modify the initial environment using `f`.
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> type Env = String
* scala> type GlobalEnv = (Int, Env)
* scala> type Log = List[String]
@@ -48,7 +69,7 @@ final class IndexedReaderWriterStateT[F[_], E, L, SA, SB, A](val runF: F[(E, SA)
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val x: IndexedReaderWriterStateT[Option, String, String, Int, Int, Unit] = IndexedReaderWriterStateT.tell("something")
* scala> val y: IndexedReaderWriterStateT[Option, String, String, Int, Int, (Unit, String)] = x.listen
* scala> y.run("environment", 17)
@@ -146,7 +167,7 @@ final class IndexedReaderWriterStateT[F[_], E, L, SA, SB, A](val runF: F[(E, SA)
* Like [[transform]], but allows the context to change from `F` to `G`.
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> type ErrorOr[A] = Either[String, A]
* scala> type Env = String
* scala> type Log = List[String]
@@ -168,7 +189,7 @@ final class IndexedReaderWriterStateT[F[_], E, L, SA, SB, A](val runF: F[(E, SA)
* Like [[transform]], but does it in the monadic context `F`.
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> type Env = String
* scala> type Log = List[String]
* scala> val xOpt0: IndexedReaderWriterStateT[Option, Env, Log, Int, Int, Int] = IndexedReaderWriterStateT.get
@@ -190,7 +211,7 @@ final class IndexedReaderWriterStateT[F[_], E, L, SA, SB, A](val runF: F[(E, SA)
* Transform the state used. See [[StateT]] for more details.
*
* {{{
- * scala> import cats.implicits._ // needed for StateT.apply
+ * scala> import cats.syntax.all._ // needed for StateT.apply
* scala> type Env = String
* scala> type Log = List[String]
* scala> type S[SA, SB, A] = IndexedReaderWriterStateT[Option, Env, Log, SA, SB, A]
@@ -225,7 +246,7 @@ final class IndexedReaderWriterStateT[F[_], E, L, SA, SB, A](val runF: F[(E, SA)
* Inspect a value from the input state, without modifying the state.
*/
def inspect[B](f: SB => B)(implicit F: Functor[F]): IndexedReaderWriterStateT[F, E, L, SA, SB, B] =
- transform { (l, sb, a) =>
+ transform { (l, sb, _) =>
(l, sb, f(sb))
}
@@ -233,7 +254,7 @@ final class IndexedReaderWriterStateT[F[_], E, L, SA, SB, A](val runF: F[(E, SA)
* Inspect a value from the environment and input state, without modifying the state.
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> type Env = String
* scala> type Log = List[String]
* scala> val xOpt: IndexedReaderWriterStateT[Option, Env, Log, Int, Int, Int] = IndexedReaderWriterStateT.get
@@ -266,7 +287,7 @@ final class IndexedReaderWriterStateT[F[_], E, L, SA, SB, A](val runF: F[(E, SA)
* Retrieve the value written to the log.
*/
def written(implicit F: Functor[F]): IndexedReaderWriterStateT[F, E, L, SA, SB, L] =
- transform { (l, sb, a) =>
+ transform { (l, sb, _) =>
(l, sb, l)
}
diff --git a/core/src/main/scala/cats/data/IndexedStateT.scala b/core/src/main/scala/cats/data/IndexedStateT.scala
index b3ae45afd5..8cfec758a6 100644
--- a/core/src/main/scala/cats/data/IndexedStateT.scala
+++ b/core/src/main/scala/cats/data/IndexedStateT.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -106,7 +127,7 @@ final class IndexedStateT[F[_], SA, SB, A](val runF: F[SA => F[(SB, A)]]) extend
* Like [[transform]], but allows the context to change from `F` to `G`.
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> type ErrorOr[A] = Either[String, A]
* scala> val xError: IndexedStateT[ErrorOr, Int, Int, Int] = IndexedStateT.get
* scala> val xOpt: IndexedStateT[Option, Int, Int, Int] = xError.transformF(_.toOption)
@@ -129,7 +150,7 @@ final class IndexedStateT[F[_], SA, SB, A](val runF: F[SA => F[(SB, A)]]) extend
* global state containing the various states needed for each individual `StateT`.
*
* {{{
- * scala> import cats.implicits._ // needed for StateT.apply
+ * scala> import cats.syntax.all._ // needed for StateT.apply
* scala> type GlobalEnv = (Int, String)
* scala> val x: StateT[Option, Int, Double] = StateT((x: Int) => Option((x + 1, x.toDouble)))
* scala> val xt: StateT[Option, GlobalEnv, Double] = x.transformS[GlobalEnv](_._1, (t, i) => (i, t._2))
@@ -258,7 +279,7 @@ sealed abstract private[data] class IndexedStateTInstances extends IndexedStateT
implicit def catsDataAlternativeForIndexedStateT[F[_], S](implicit
FM: Monad[F],
FA: Alternative[F]
- ): Alternative[IndexedStateT[F, S, S, *]] with Monad[IndexedStateT[F, S, S, *]] =
+ ): Alternative[IndexedStateT[F, S, S, *]] & Monad[IndexedStateT[F, S, S, *]] =
new IndexedStateTAlternative[F, S] { implicit def F = FM; implicit def G = FA }
implicit def catsDataDeferForIndexedStateT[F[_], SA, SB](implicit F: Defer[F]): Defer[IndexedStateT[F, SA, SB, *]] =
@@ -461,8 +482,8 @@ sealed abstract private[data] class IndexedStateTContravariantMonoidal[F[_], S]
implicit def F: ContravariantMonoidal[F]
implicit def G: Applicative[F]
- override def unit: IndexedStateT[F, S, S, Unit] =
- IndexedStateT.applyF(G.pure((s: S) => F.trivial[(S, Unit)]))
+ override val unit: IndexedStateT[F, S, S, Unit] =
+ IndexedStateT.applyF(G.pure((_: S) => F.trivial[(S, Unit)]))
override def contramap[A, B](fa: IndexedStateT[F, S, S, A])(f: B => A): IndexedStateT[F, S, S, B] =
contramap2(fa, trivial)(((a: A) => (a, a)).compose(f))
diff --git a/core/src/main/scala/cats/data/Ior.scala b/core/src/main/scala/cats/data/Ior.scala
index 274b2f7548..f7aaf6a093 100644
--- a/core/src/main/scala/cats/data/Ior.scala
+++ b/core/src/main/scala/cats/data/Ior.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -29,7 +50,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val rightF: Int => String = _.show
* scala> val bothF: (String,Int) => String = (a,b) => a.combine(b.show)
@@ -58,7 +79,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val ior1 = "abc".leftIor[Int]
* scala> ior1.putLeft(true)
@@ -80,7 +101,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val ior1 = "abc".leftIor[Int]
* scala> ior1.putRight(123L)
@@ -99,14 +120,14 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
fold(Ior.both(_, right), _ => Ior.right(right), (a, _) => Ior.both(a, right))
/**
- * When a Left value is present in the Ior, combine it will the value specified.
+ * When a Left value is present in the Ior, combine it with the value specified.
*
* When the Left value is absent, set it to the value specified.
*
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val ior1 = "abc".leftIor[Int]
* scala> ior1.addLeft("def")
@@ -125,14 +146,14 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
fold(l => Ior.left(AA.combine(l, left)), Ior.both(left, _), (l, r) => Ior.both(AA.combine(l, left), r))
/**
- * When a Right value is present in the Ior, combine it will the value specified.
+ * When a Right value is present in the Ior, combine it with the value specified.
*
* When the Right value is absent, set it to the value specified.
*
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val ior1 = "abc".leftIor[Int]
* scala> ior1.addRight(123)
@@ -154,7 +175,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].isLeft
* res0: Boolean = true
@@ -166,15 +187,29 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* res2: Boolean = false
* }}}
*/
- final def isLeft: Boolean = fold(_ => true, _ => false, (_, _) => false)
- final def isRight: Boolean = fold(_ => false, _ => true, (_, _) => false)
- final def isBoth: Boolean = fold(_ => false, _ => false, (_, _) => true)
+ final def isLeft: Boolean =
+ this match {
+ case Ior.Left(_) => true
+ case _ => false
+ }
+
+ final def isRight: Boolean =
+ this match {
+ case Ior.Right(_) => true
+ case _ => false
+ }
+
+ final def isBoth: Boolean =
+ this match {
+ case Ior.Both(_, _) => true
+ case _ => false
+ }
/**
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].left
* res0: Option[String] = Some(abc)
@@ -192,7 +227,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].right
* res0: Option[Int] = None
@@ -204,13 +239,18 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* res2: Option[Int] = Some(123)
* }}}
*/
- final def right: Option[B] = fold(_ => None, b => Some(b), (_, b) => Some(b))
+ final def right: Option[B] =
+ this match {
+ case Ior.Right(b) => Some(b)
+ case Ior.Both(_, b) => Some(b)
+ case Ior.Left(_) => None
+ }
/**
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].onlyLeft
* res0: Option[String] = Some(abc)
@@ -228,7 +268,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].onlyRight
* res0: Option[Int] = None
@@ -246,7 +286,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].onlyLeftOrRight
* res0: Option[Either[String, Int]] = Some(Left(abc))
@@ -264,7 +304,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].onlyBoth
* res0: Option[(String, Int)] = None
@@ -282,7 +322,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].pad
* res0: (Option[String], Option[Int]) = (Some(abc),None)
@@ -300,7 +340,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].unwrap
* res0: Either[Either[String, Int], (String, Int)] = Left(Left(abc))
@@ -319,7 +359,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].toIorNes
* res0: IorNes[String, Int] = Left(TreeSet(abc))
@@ -339,7 +379,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].toIorNel
* res0: IorNel[String, Int] = Left(NonEmptyList(abc))
@@ -357,7 +397,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].toEither
* res0: Either[String, Int] = Left(abc)
@@ -375,7 +415,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].toValidated
* res0: Validated[String, Int] = Invalid(abc)
@@ -393,7 +433,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].toOption
* res0: Option[Int] = None
@@ -411,7 +451,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].toList
* res0: List[Int] = List()
@@ -429,7 +469,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].to[List, Int]
* res0: List[Int] = List()
@@ -448,7 +488,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].swap
* res0: Ior[Int, String] = Right(abc)
@@ -466,7 +506,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].exists(_ > 100)
* res0: Boolean = false
@@ -484,7 +524,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].forall(_ > 100)
* res0: Boolean = true
@@ -502,7 +542,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].getOrElse(456)
* res0: Int = 456
@@ -520,7 +560,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].valueOr(_.length)
* res0: Int = 3
@@ -539,7 +579,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].bimap(_.length, identity)
* res0: Ior[Int, Int] = Left(3)
@@ -558,7 +598,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].map(_ * 2)
* res0: Ior[String, Int] = Left(abc)
@@ -576,7 +616,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].leftMap(_.length)
* res0: Ior[Int, Int] = Left(3)
@@ -594,7 +634,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].flatMap(i => 456.rightIor[String])
* res0: Ior[String, Int] = Left(abc)
@@ -631,7 +671,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* // Nothing to show
* scala> "abc".leftIor[Int].foreach(println)
@@ -655,7 +695,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].traverse(i => List(i, i * 2))
* res0: List[Ior[String,Int]] = List(Left(abc))
@@ -678,7 +718,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].foldLeft(List(456))((c,b) => b :: c)
* res0: List[Int] = List(456)
@@ -709,7 +749,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "abc".leftIor[Int].combine("other".leftIor[Int])
* res0: Ior[String, Int] = Left(abcother)
@@ -753,11 +793,12 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
}
final def ===[AA >: A, BB >: B](that: AA Ior BB)(implicit AA: Eq[AA], BB: Eq[BB]): Boolean =
- fold(
- a => that.fold(a2 => AA.eqv(a, a2), b2 => false, (a2, b2) => false),
- b => that.fold(a2 => false, b2 => BB.eqv(b, b2), (a2, b2) => false),
- (a, b) => that.fold(a2 => false, b2 => false, (a2, b2) => AA.eqv(a, a2) && BB.eqv(b, b2))
- )
+ (this, that) match {
+ case (Ior.Left(a), Ior.Left(aa)) => AA.eqv(a, aa)
+ case (Ior.Right(b), Ior.Right(bb)) => BB.eqv(b, bb)
+ case (Ior.Both(a, b), Ior.Both(aa, bb)) => AA.eqv(a, aa) && BB.eqv(b, bb)
+ case _ => false
+ }
final def compare[AA >: A, BB >: B](that: AA Ior BB)(implicit AA: Order[AA], BB: Order[BB]): Int =
(this, that) match {
@@ -817,21 +858,11 @@ sealed abstract private[data] class IorInstances extends IorInstances0 {
}
}
- implicit def catsDataOrderForIor[A: Order, B: Order]: Order[A Ior B] =
- new Order[A Ior B] {
-
- def compare(x: Ior[A, B], y: Ior[A, B]): Int = x.compare(y)
- }
+ implicit def catsDataOrderForIor[A: Order, B: Order]: Order[A Ior B] = _ compare _
- implicit def catsDataShowForIor[A: Show, B: Show]: Show[A Ior B] =
- new Show[A Ior B] {
- def show(f: A Ior B): String = f.show
- }
+ implicit def catsDataShowForIor[A: Show, B: Show]: Show[A Ior B] = _.show
- implicit def catsDataSemigroupForIor[A: Semigroup, B: Semigroup]: Semigroup[Ior[A, B]] =
- new Semigroup[Ior[A, B]] {
- def combine(x: Ior[A, B], y: Ior[A, B]) = x.combine(y)
- }
+ implicit def catsDataSemigroupForIor[A: Semigroup, B: Semigroup]: Semigroup[Ior[A, B]] = _ combine _
implicit def catsDataMonadErrorForIor[A: Semigroup]: MonadError[Ior[A, *], A] =
new MonadError[Ior[A, *], A] {
@@ -908,9 +939,9 @@ sealed abstract private[data] class IorInstances extends IorInstances0 {
}
case Ior.Left(e1) =>
ff match {
- case Ior.Right(f) => Ior.Left(e1)
- case Ior.Both(e2, f) => Ior.Left(E.combine(e2, e1))
case Ior.Left(e2) => Ior.Left(E.combine(e2, e1))
+ case Ior.Both(e2, _) => Ior.Left(E.combine(e2, e1))
+ case Ior.Right(_) => Ior.Left(e1)
}
}
}
@@ -926,12 +957,24 @@ sealed abstract private[data] class IorInstances0 {
new Traverse[Ior[A, *]] {
def traverse[F[_]: Applicative, B, C](fa: A Ior B)(f: B => F[C]): F[A Ior C] =
fa.traverse(f)
+
+ override def mapAccumulate[S, B, C](init: S, fa: Ior[A, B])(f: (S, B) => (S, C)): (S, Ior[A, C]) =
+ fa match {
+ case l @ Ior.Left(_) => (init, l)
+ case Ior.Right(b) =>
+ val (snext, c) = f(init, b)
+ (snext, Ior.Right(c))
+ case Ior.Both(a, b) =>
+ val (snext, c) = f(init, b)
+ (snext, Ior.Both(a, c))
+ }
def foldLeft[B, C](fa: A Ior B, b: C)(f: (C, B) => C): C =
fa.foldLeft(b)(f)
def foldRight[B, C](fa: A Ior B, lc: Eval[C])(f: (B, Eval[C]) => Eval[C]): Eval[C] =
fa.foldRight(lc)(f)
- override def size[B](fa: A Ior B): Long = fa.fold(_ => 0L, _ => 1L, (_, _) => 1L)
+ override def size[B](fa: A Ior B): Long =
+ if (fa.isLeft) 0L else 1L
override def get[B](fa: A Ior B)(idx: Long): Option[B] =
if (idx == 0L) fa.toOption else None
@@ -944,11 +987,7 @@ sealed abstract private[data] class IorInstances0 {
fa.map(f)
}
- implicit def catsDataEqForIor[A: Eq, B: Eq]: Eq[A Ior B] =
- new Eq[A Ior B] {
-
- def eqv(x: A Ior B, y: A Ior B): Boolean = x === y
- }
+ implicit def catsDataEqForIor[A: Eq, B: Eq]: Eq[A Ior B] = _ === _
}
sealed private[data] trait IorFunctions {
diff --git a/core/src/main/scala/cats/data/IorT.scala b/core/src/main/scala/cats/data/IorT.scala
index 5e088b05c1..1b493635e9 100644
--- a/core/src/main/scala/cats/data/IorT.scala
+++ b/core/src/main/scala/cats/data/IorT.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -8,6 +29,21 @@ final case class IorT[F[_], A, B](value: F[Ior[A, B]]) {
def fold[C](fa: A => C, fb: B => C, fab: (A, B) => C)(implicit F: Functor[F]): F[C] =
F.map(value)(_.fold(fa, fb, fab))
+ /**
+ * Transform this `IorT[F, A, B]` into a `F[C]`.
+ *
+ * Example:
+ * {{{
+ * scala> import cats.data.{Ior, IorT}
+ *
+ * scala> val iorT: IorT[List, String, Int] = IorT[List, String, Int](List(Ior.Right(123),Ior.Left("abc"), Ior.Both("abc", 123)))
+ * scala> iorT.foldF(string => string.split("").toList, int => List(int.toString), (string, int) => string.split("").toList ++ List(int.toString))
+ * val res0: List[String] = List(123, a, b, c, a, b, c, 123)
+ * }}}
+ */
+ def foldF[C](fa: A => F[C], fb: B => F[C], fab: (A, B) => F[C])(implicit F: FlatMap[F]): F[C] =
+ F.flatMap(value)(_.fold(fa, fb, fab))
+
def isLeft(implicit F: Functor[F]): F[Boolean] = F.map(value)(_.isLeft)
def isRight(implicit F: Functor[F]): F[Boolean] = F.map(value)(_.isRight)
@@ -25,6 +61,26 @@ final case class IorT[F[_], A, B](value: F[Ior[A, B]]) {
case Ior.Both(_, b) => F.pure(b)
}
+ /***
+ *
+ * Like [[getOrElseF]] but accept an error `E` and raise it when the inner `Ior` is `Left`
+ *
+ * Equivalent to `getOrElseF(F.raiseError(e)))`
+ *
+ * Example:
+ * {{{
+ * scala> import cats.data.IorT
+ * scala> import cats.syntax.all._
+ * scala> import scala.util.{Success, Failure, Try}
+
+ * scala> val iorT: IorT[Try,String,Int] = IorT.leftT("abc")
+ * scala> iorT.getOrRaise(new RuntimeException("ERROR!"))
+ * res0: Try[Int] = Failure(java.lang.RuntimeException: ERROR!)
+ * }}}
+ */
+ def getOrRaise[E](e: => E)(implicit F: MonadError[F, ? >: E]): F[B] =
+ getOrElseF(F.raiseError(e))
+
def valueOr[BB >: B](f: A => BB)(implicit F: Functor[F], BB: Semigroup[BB]): F[BB] = F.map(value)(_.valueOr(f))
def forall(f: B => Boolean)(implicit F: Functor[F]): F[Boolean] = F.map(value)(_.forall(f))
@@ -139,7 +195,7 @@ object IorT extends IorTInstances {
* Creates a left version of `IorT[F, A, B]` from a `F[A]`
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> IorT.left[Int](Option("err"))
* res0: cats.data.IorT[Option,String,Int] = IorT(Some(Left(err)))
* }}}
@@ -157,7 +213,7 @@ object IorT extends IorTInstances {
* Creates a left version of `IorT[F, A, B]` from a `A`
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> IorT.leftT[Option, Int]("err")
* res0: cats.data.IorT[Option,String,Int] = IorT(Some(Left(err)))
*
@@ -176,7 +232,7 @@ object IorT extends IorTInstances {
* Creates a right version of `IorT[F, A, B]` from a `F[B]`
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> IorT.right[String](Option(3))
* res0: cats.data.IorT[Option,String,Int] = IorT(Some(Right(3)))
* }}}
@@ -187,7 +243,7 @@ object IorT extends IorTInstances {
* Alias for [[pure]]
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> IorT.rightT[Option, String](3)
* res0: cats.data.IorT[Option,String,Int] = IorT(Some(Right(3)))
* }}}
@@ -198,7 +254,7 @@ object IorT extends IorTInstances {
* Creates a both version of `IorT[F, A, B]` from a `F[A]` and a `F[B]`
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> IorT.both(Option("err"), Option(3))
* res0: cats.data.IorT[Option,String,Int] = IorT(Some(Both(err,3)))
* }}}
@@ -217,7 +273,7 @@ object IorT extends IorTInstances {
* Creates a both version of `IorT[F, A, B]` from a `A` and a `B`
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> IorT.bothT[Option]("err", 3)
* res0: cats.data.IorT[Option,String,Int] = IorT(Some(Both(err,3)))
* }}}
@@ -235,7 +291,7 @@ object IorT extends IorTInstances {
* Creates a right version of `IorT[F, A, B]` from a `B`
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> IorT.pure[Option, String](3)
* res0: cats.data.IorT[Option,String,Int] = IorT(Some(Right(3)))
* }}}
@@ -246,7 +302,7 @@ object IorT extends IorTInstances {
* Alias for [[right]]
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val o: Option[Int] = Some(3)
* scala> val n: Option[Int] = None
* scala> IorT.liftF(o)
@@ -283,7 +339,7 @@ object IorT extends IorTInstances {
* Transforms an `Ior` into an `IorT`, lifted into the specified `Applicative`.
* {{{
* scala> import cats.data.{IorT, Ior}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val i: Ior[String, Int] = Ior.both("warning", 3)
* scala> IorT.fromIor[Option](i)
* res0: cats.data.IorT[Option,String,Int] = IorT(Some(Both(warning,3)))
@@ -303,7 +359,7 @@ object IorT extends IorTInstances {
* Transforms an `Either` into an `IorT`, lifted into the specified `Applicative`.
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val e: Either[String, Int] = Either.right(3)
* scala> IorT.fromEither[Option](e)
* res0: cats.data.IorT[Option,String,Int] = IorT(Some(Right(3)))
@@ -315,7 +371,7 @@ object IorT extends IorTInstances {
* Transforms an `F[Either]` into an `IorT`.
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val e: Either[String, Int] = Either.right(3)
* scala> IorT.fromEitherF(Option(e))
* res0: cats.data.IorT[Option,String,Int] = IorT(Some(Right(3)))
@@ -337,7 +393,7 @@ object IorT extends IorTInstances {
* the second argument if the `Option` is a `None`.
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val o: Option[Int] = None
* scala> IorT.fromOption[List](o, "Answer not known.")
* res0: cats.data.IorT[List,String,Int] = IorT(List(Left(Answer not known.)))
@@ -351,7 +407,7 @@ object IorT extends IorTInstances {
* Transforms an `F[Option]` into an `IorT`, using the second argument if the `Option` is a `None`.
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val o: Option[Int] = None
* scala> IorT.fromOptionF(List(o), "Answer not known.")
* res0: cats.data.IorT[List,String,Int] = IorT(List(Left(Answer not known.)))
@@ -386,7 +442,7 @@ object IorT extends IorTInstances {
* `A` in `Ior.Left`, lifted into the specified `Applicative`.
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val userInput = "hello world"
* scala> IorT.cond[Option](
* | userInput.forall(_.isDigit) && userInput.size == 10,
@@ -402,7 +458,7 @@ object IorT extends IorTInstances {
* value of `IorT.left` on `F[A]`.
* {{{
* scala> import cats.data.IorT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val userInput = "hello world"
* scala> IorT.condF[Option, String, String](
* | userInput.forall(_.isDigit) && userInput.size == 10,
diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala
index 2374161467..fac3cb6949 100644
--- a/core/src/main/scala/cats/data/Kleisli.scala
+++ b/core/src/main/scala/cats/data/Kleisli.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -25,7 +46,7 @@ final case class Kleisli[F[_], -A, B](run: A => F[B]) { self =>
* Performs [[local]] and [[map]] simultaneously.
*/
def dimap[C, D](f: C => A)(g: B => D)(implicit F: Functor[F]): Kleisli[F, C, D] =
- Kleisli(c => F.map(run(f(c)))(g))
+ Kleisli(run.compose(f).andThen(F.map(_)(g)))
/**
* Modify the output of the Kleisli function with `f`.
@@ -36,29 +57,34 @@ final case class Kleisli[F[_], -A, B](run: A => F[B]) { self =>
* res0: Option[Double] = Some(1.0)
* }}}
*/
- def map[C](f: B => C)(implicit F: Functor[F]): Kleisli[F, A, C] =
- Kleisli(a => F.map(run(a))(f))
+ def map[C](f: B => C)(implicit F: Functor[F]): Kleisli[F, A, C] = mapF(F.map(_)(f))
+
+ def mapF[N[_], C](f: F[B] => N[C]): Kleisli[N, A, C] = Kleisli(run.andThen(f))
- def mapF[N[_], C](f: F[B] => N[C]): Kleisli[N, A, C] =
- Kleisli(a => f(run(a)))
+ def mapFilter[B1](f: B => Option[B1])(implicit F: FunctorFilter[F]): Kleisli[F, A, B1] =
+ Kleisli[F, A, B1](run.andThen(F.mapFilter(_)(f)))
/**
* Modify the context `F` using transformation `f`.
*/
- def mapK[G[_]](f: F ~> G): Kleisli[G, A, B] =
- Kleisli[G, A, B](a => f(run(a)))
+ def mapK[G[_]](f: F ~> G): Kleisli[G, A, B] = mapF(f.apply)
def flatMap[C, AA <: A](f: B => Kleisli[F, AA, C])(implicit F: FlatMap[F]): Kleisli[F, AA, C] =
- Kleisli.shift(a => F.flatMap[B, C](run(a))((b: B) => f(b).run(a)))
+ run match {
+ case StrictConstFunction1(fb) => Kleisli(a => F.flatMap(fb)(f(_).run(a)))
+ case _ => Kleisli.shift(a => F.flatMap[B, C](run(a))(f(_).run(a)))
+ }
- def flatMapF[C](f: B => F[C])(implicit F: FlatMap[F]): Kleisli[F, A, C] =
- Kleisli.shift(a => F.flatMap(run(a))(f))
+ def flatMapF[C](f: B => F[C])(implicit F: FlatMap[F]): Kleisli[F, A, C] = run match {
+ case run: StrictConstFunction1[?] => Kleisli(run.andThen(F.flatMap(_: F[B])(f)))
+ case _ => Kleisli.shift(a => F.flatMap(run(a))(f))
+ }
/**
* Composes [[run]] with a function `B => F[C]` not lifted into Kleisli.
*/
def andThen[C](f: B => F[C])(implicit F: FlatMap[F]): Kleisli[F, A, C] =
- Kleisli.shift(a => F.flatMap(run(a))(f))
+ flatMapF(f)
/**
* Tip to tail Kleisli arrow composition.
@@ -78,13 +104,13 @@ final case class Kleisli[F[_], -A, B](run: A => F[B]) { self =>
Kleisli.shift((z: Z) => F.flatMap(f(z))(run))
def compose[Z, AA <: A](k: Kleisli[F, Z, AA])(implicit F: FlatMap[F]): Kleisli[F, Z, B] =
- this.compose(k.run)
+ k.andThen(this)
def traverse[G[_], AA <: A](f: G[AA])(implicit F: Applicative[F], G: Traverse[G]): F[G[B]] =
G.traverse(f)(run)
def lift[G[_]](implicit G: Applicative[G]): Kleisli[λ[α => G[F[α]]], A, B] =
- Kleisli[λ[α => G[F[α]]], A, B](a => Applicative[G].pure(run(a)))
+ mapF[λ[α => G[F[α]]], B](G.pure)
/**
* Contramap the input using `f`, where `f` may modify the input type of the Kleisli arrow.
@@ -97,14 +123,14 @@ final case class Kleisli[F[_], -A, B](run: A => F[B]) { self =>
* }}}
*/
def local[AA](f: AA => A): Kleisli[F, AA, B] =
- Kleisli(aa => run(f(aa)))
+ Kleisli(run.compose(f))
@deprecated("Use mapK", "1.0.0-RC2")
private[cats] def transform[G[_]](f: FunctionK[F, G]): Kleisli[G, A, B] =
mapK(f)
def lower(implicit F: Applicative[F]): Kleisli[F, A, F[B]] =
- Kleisli(a => F.pure(run(a)))
+ mapF(F.pure)
def first[C](implicit F: Functor[F]): Kleisli[F, (A, C), (B, C)] =
Kleisli { case (a, c) => F.fproduct(run(a))(_ => c) }
@@ -189,6 +215,34 @@ object Kleisli
def applyK[F[_], A](a: A): Kleisli[F, A, *] ~> F =
new (Kleisli[F, A, *] ~> F) { def apply[B](k: Kleisli[F, A, B]): F[B] = k.apply(a) }
+ /**
+ * Creates a `FunctionK` that transforms a `Kleisli[F, A, B]` into an `Kleisli[F, C, B]` using `C => A`.
+ * {{{
+ * scala> import cats.{~>}, cats.data.Kleisli
+ *
+ * scala> def nonEmpty(s: String): Option[String] = Option(s).filter(_.nonEmpty)
+ * scala> type KOS[A] = Kleisli[Option, String, A]
+ * scala> type KOLS[A] = Kleisli[Option, List[String], A]
+ * scala> val size: KOS[Int] = Kleisli(s => nonEmpty(s).map(_.size))
+ * scala> val exclaim: KOS[String] = Kleisli(s => nonEmpty(s).map(nes => s"${nes.toUpperCase}!"))
+ * scala> size("boo")
+ * res0: Option[Int] = Some(3)
+ *
+ * scala> exclaim("boo")
+ * res1: Option[String] = Some(BOO!)
+ *
+ * scala> val mkStringK: KOS ~> KOLS = Kleisli.localK(_.mkString)
+ * scala> mkStringK(size)(List("foo", "bar", "baz"))
+ * res2: Option[Int] = Some(9)
+ *
+ * scala> mkStringK(exclaim)(List("foo", "bar", "baz"))
+ * res3: Option[String] = Some(FOOBARBAZ!)
+ * }}}
+ */
+ def localK[F[_], A, C](f: C => A): Kleisli[F, A, *] ~> Kleisli[F, C, *] =
+ new (Kleisli[F, A, *] ~> Kleisli[F, C, *]) {
+ def apply[B](k: Kleisli[F, A, B]): Kleisli[F, C, B] = k.local(f)
+ }
}
sealed private[data] trait KleisliFunctions {
@@ -204,7 +258,7 @@ sealed private[data] trait KleisliFunctions {
* }}}
*/
def liftF[F[_], A, B](x: F[B]): Kleisli[F, A, B] =
- Kleisli(_ => x)
+ Kleisli(StrictConstFunction1(x))
/**
* Same as [[liftF]], but expressed as a FunctionK for use with mapK
@@ -221,7 +275,7 @@ sealed private[data] trait KleisliFunctions {
@deprecated("Use liftF instead", "1.0.0-RC2")
private[cats] def lift[F[_], A, B](x: F[B]): Kleisli[F, A, B] =
- Kleisli(_ => x)
+ liftF(x)
/**
* Creates a Kleisli arrow ignoring its input and lifting the given `B` into applicative context `F`.
@@ -233,7 +287,7 @@ sealed private[data] trait KleisliFunctions {
* }}}
*/
def pure[F[_], A, B](x: B)(implicit F: Applicative[F]): Kleisli[F, A, B] =
- Kleisli(_ => F.pure(x))
+ liftF(F.pure(x))
/**
* Creates a Kleisli arrow which can lift an `A` into applicative context `F`.
@@ -255,8 +309,7 @@ sealed private[data] trait KleisliFunctions {
* res0: Option[Int] = Some(1)
* }}}
*/
- def local[M[_], A, R](f: R => R)(fa: Kleisli[M, R, A]): Kleisli[M, R, A] =
- Kleisli(r => fa.run(f(r)))
+ def local[M[_], A, R](f: R => R)(fa: Kleisli[M, R, A]): Kleisli[M, R, A] = fa.local(f)
/**
* Lifts a function to a Kleisli.
@@ -336,7 +389,7 @@ sealed abstract private[data] class KleisliInstances0 extends KleisliInstances0_
implicit def catsDataCommutativeArrowForKleisli[F[_]](implicit
M: CommutativeMonad[F]
- ): CommutativeArrow[Kleisli[F, *, *]] with ArrowChoice[Kleisli[F, *, *]] =
+ ): CommutativeArrow[Kleisli[F, *, *]] & ArrowChoice[Kleisli[F, *, *]] =
new KleisliCommutativeArrow[F] { def F: CommutativeMonad[F] = M }
implicit def catsDataCommutativeMonadForKleisli[F[_], A](implicit
@@ -388,6 +441,14 @@ sealed abstract private[data] class KleisliInstances0_5 extends KleisliInstances
def tabulate[A](f: Representation => A): Kleisli[M, E, A] =
Kleisli[M, E, A](e => R.tabulate(r => f((e, r))))
}
+
+ implicit def catsDataAlignForKleisli[F[_], R](implicit
+ evFunctor: Functor[Kleisli[F, R, *]],
+ evAlign: Align[F]
+ ): Align[Kleisli[F, R, *]] = new KleisliAlign[F, R] {
+ override val functor: Functor[Kleisli[F, R, *]] = evFunctor
+ override val FA: Align[F] = evAlign
+ }
}
sealed abstract private[data] class KleisliInstances1 extends KleisliInstances2 {
@@ -681,7 +742,7 @@ private[data] trait KleisliFunctor[F[_], A] extends Functor[Kleisli[F, A, *]] {
fa.map(f)
override def void[B](fa: Kleisli[F, A, B]): Kleisli[F, A, Unit] =
- Kleisli(a => F.void(fa.run(a)))
+ Kleisli(fa.run.andThen(F.void))
}
private trait KleisliDistributive[F[_], R] extends Distributive[Kleisli[F, R, *]] {
@@ -693,14 +754,18 @@ private trait KleisliDistributive[F[_], R] extends Distributive[Kleisli[F, R, *]
def map[A, B](fa: Kleisli[F, R, A])(f: A => B): Kleisli[F, R, B] = fa.map(f)
}
+private trait KleisliAlign[F[_], R] extends Align[Kleisli[F, R, *]] {
+ def FA: Align[F]
+
+ override def align[A, B](fa: Kleisli[F, R, A], fb: Kleisli[F, R, B]): Kleisli[F, R, Ior[A, B]] =
+ Kleisli(r => FA.align(fa.run(r), fb.run(r)))
+}
+
private[this] trait KleisliFunctorFilter[F[_], R] extends FunctorFilter[Kleisli[F, R, *]] {
def FF: FunctorFilter[F]
def functor: Functor[Kleisli[F, R, *]] = Kleisli.catsDataFunctorForKleisli(FF.functor)
- def mapFilter[A, B](fa: Kleisli[F, R, A])(f: A => Option[B]): Kleisli[F, R, B] =
- Kleisli[F, R, B] { r =>
- FF.mapFilter(fa.run(r))(f)
- }
+ def mapFilter[A, B](fa: Kleisli[F, R, A])(f: A => Option[B]): Kleisli[F, R, B] = fa.mapFilter(f)(FF)
}
diff --git a/core/src/main/scala/cats/data/Nested.scala b/core/src/main/scala/cats/data/Nested.scala
index 7c17c8f8ca..5b50fbd9b0 100644
--- a/core/src/main/scala/cats/data/Nested.scala
+++ b/core/src/main/scala/cats/data/Nested.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -11,7 +32,7 @@ package data
* {{{
* scala> import cats.Functor
* scala> import cats.data.Nested
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val listOption: List[Option[Int]] = List(Some(1), None)
* scala> val f: Int => String = i => (i * 2).toString
* scala> Functor[List].map(listOption)(opt => opt.map(f))
@@ -96,7 +117,7 @@ sealed abstract private[data] class NestedInstances0 extends NestedInstances1 {
): Representable.Aux[Nested[F, G, *], (F0.Representation, G0.Representation)] = new Representable[Nested[F, G, *]] {
val FG = F0.compose(G0)
- val F = new NestedFunctor[F, G] {
+ val F: Functor[Nested[F, G, *]] = new NestedFunctor[F, G] {
val FG = F0.F.compose(G0.F)
}
@@ -326,6 +347,15 @@ private[data] trait NestedTraverse[F[_], G[_]]
override def traverse[H[_]: Applicative, A, B](fga: Nested[F, G, A])(f: A => H[B]): H[Nested[F, G, B]] =
Applicative[H].map(FG.traverse(fga.value)(f))(Nested(_))
+
+ override def mapAccumulate[S, A, B](init: S, fga: Nested[F, G, A])(f: (S, A) => (S, B)): (S, Nested[F, G, B]) = {
+ val (finalState, fgb) = FG.mapAccumulate(init, fga.value)(f)
+ (finalState, Nested(fgb))
+ }
+
+ override def mapWithIndex[A, B](fga: Nested[F, G, A])(f: (A, Int) => B): Nested[F, G, B] = {
+ Nested(FG.mapWithIndex(fga.value)(f))
+ }
}
private[data] trait NestedDistributive[F[_], G[_]] extends Distributive[Nested[F, G, *]] with NestedFunctor[F, G] {
diff --git a/core/src/main/scala/cats/data/Newtype.scala b/core/src/main/scala/cats/data/Newtype.scala
index 3aa8566357..363d832569 100644
--- a/core/src/main/scala/cats/data/Newtype.scala
+++ b/core/src/main/scala/cats/data/Newtype.scala
@@ -1,14 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
/**
* Helper trait for `newtype`s. These allow you to create a zero-allocation wrapper around a specific type.
* Similar to `AnyVal` value classes, but never have any runtime overhead.
- * It's coped from the newtypes lib by @alexknvl
+ * It's copied from the newtypes lib by @alexknvl
* For more detail see https://github.com/alexknvl/newtypes
*/
private[data] trait Newtype { self =>
private[data] type Base
private[data] trait Tag extends Any
- type Type[A] <: Base with Tag
+ type Type[A] <: Base & Tag
}
diff --git a/core/src/main/scala/cats/data/Newtype2.scala b/core/src/main/scala/cats/data/Newtype2.scala
index a6307cdc73..404b80bbde 100644
--- a/core/src/main/scala/cats/data/Newtype2.scala
+++ b/core/src/main/scala/cats/data/Newtype2.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -9,5 +30,5 @@ package data
private[data] trait Newtype2 { self =>
private[data] type Base
private[data] trait Tag extends Any
- type Type[A, +B] <: Base with Tag
+ type Type[A, +B] <: Base & Tag
}
diff --git a/core/src/main/scala/cats/data/NonEmptyChain.scala b/core/src/main/scala/cats/data/NonEmptyChain.scala
index 6d0f53f6ea..05abcb7dc0 100644
--- a/core/src/main/scala/cats/data/NonEmptyChain.scala
+++ b/core/src/main/scala/cats/data/NonEmptyChain.scala
@@ -1,11 +1,40 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
-import NonEmptyChainImpl.create
+import cats.instances.StaticMethods
import cats.kernel._
+
import scala.collection.immutable.SortedMap
-private[data] object NonEmptyChainImpl extends NonEmptyChainInstances with ScalaVersionSpecificNonEmptyChainImpl {
+/**
+ * Actual implementation for [[cats.data.NonEmptyChain]]
+ *
+ * @note This object is kept public for the sake of binary compatibility only
+ * and therefore is subject to changes in future versions of Cats.
+ * Do not use directly - use [[cats.data.NonEmptyChain]] instead.
+ */
+object NonEmptyChainImpl extends NonEmptyChainInstances with ScalaVersionSpecificNonEmptyChainImpl {
// The following 3 types are components of a technique to
// create a no-boxing newtype. It's copied from the
// newtypes lib by @alexknvl
@@ -13,7 +42,7 @@ private[data] object NonEmptyChainImpl extends NonEmptyChainInstances with Scala
private[data] type Base
private[data] trait Tag extends Any
/* aliased in data package as NonEmptyChain */
- type Type[+A] <: Base with Tag
+ type Type[+A] <: Base & Tag
private[data] def create[A](s: Chain[A]): Type[A] =
s.asInstanceOf[Type[A]]
@@ -59,10 +88,12 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
extends AnyVal
with NonEmptyCollection[A, Chain, NonEmptyChain] {
+ import NonEmptyChainImpl.{create, unwrap}
+
/**
* Converts this chain to a `Chain`
*/
- final def toChain: Chain[A] = NonEmptyChainImpl.unwrap(value)
+ final def toChain: Chain[A] = unwrap(value)
/**
* Returns a new NonEmptyChain consisting of `a` followed by this. O(1) runtime.
@@ -208,7 +239,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
* Tests if some element is contained in this chain.
* {{{
* scala> import cats.data.NonEmptyChain
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nec = NonEmptyChain(4, 5, 6)
* scala> nec.contains(5)
* res0: Boolean = true
@@ -235,7 +266,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
* Returns a new `Chain` containing all elements where the result of `pf` is final defined.
* {{{
* scala> import cats.data.NonEmptyChain
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nec = NonEmptyChain(4, 5, 6).map(n => if (n % 2 == 0) Some(n) else None)
* scala> nec.collect { case Some(n) => n }
* res0: cats.data.Chain[Int] = Chain(4, 6)
@@ -386,7 +417,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
*
* {{{
* scala> import cats.data.{NonEmptyChain, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nec = NonEmptyChain(12, -2, 3, -5)
* scala> val expectedResult = NonEmptyMap.of(false -> NonEmptyChain(-2, -5), true -> NonEmptyChain(12, 3))
* scala> val result = nec.groupBy(_ >= 0)
@@ -402,7 +433,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
*
* {{{
* scala> import cats.data.NonEmptyChain
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyChain.of(12, -2, 3, -5)
* scala> val expectedResult = List(NonEmptyChain.of(12, -2), NonEmptyChain.of(3, -5))
* scala> val result = nel.grouped(2)
@@ -421,7 +452,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
*
* {{{
* scala> import cats.data.{NonEmptyChain, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nec = NonEmptyChain(12, -2, 3, -5)
* scala> val expectedResult = NonEmptyMap.of(false -> NonEmptyChain(-2, -5), true -> NonEmptyChain(12, 3))
* scala> val result = nec.groupByNem(_ >= 0)
@@ -440,7 +471,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
*
* {{{
* scala> import cats.data.{NonEmptyChain, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nec = NonEmptyChain(12, -2, 3, -5)
* scala> val expectedResult = NonEmptyMap.of(false -> NonEmptyChain("-2", "-5"), true -> NonEmptyChain("12", "3"))
* scala> val result = nec.groupMap(_ >= 0)(_.toString)
@@ -459,7 +490,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
*
* {{{
* scala> import cats.data.{NonEmptyChain, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nec = NonEmptyChain(12, -2, 3, -5)
* scala> val expectedResult = NonEmptyMap.of(false -> NonEmptyChain("-2", "-5"), true -> NonEmptyChain("12", "3"))
* scala> val result = nec.groupMapNem(_ >= 0)(_.toString)
@@ -480,7 +511,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
*
* {{{
* scala> import cats.data.{NonEmptyChain, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nec = NonEmptyChain("Hello", "World", "Goodbye", "World")
* scala> val expectedResult = NonEmptyMap.of("goodbye" -> 1, "hello" -> 1, "world" -> 2)
* scala> val result = nec.groupMapReduce(_.trim.toLowerCase)(_ => 1)
@@ -501,7 +532,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
*
* {{{
* scala> import cats.data.{NonEmptyChain, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nec = NonEmptyChain("Hello", "World", "Goodbye", "World")
* scala> val expectedResult = NonEmptyMap.of("goodbye" -> 1, "hello" -> 1, "world" -> 2)
* scala> val result = nec.groupMapReduceNem(_.trim.toLowerCase)(_ => 1)
@@ -522,7 +553,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
*
* {{{
* scala> import cats.data.{NonEmptyChain, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nec = NonEmptyChain("Hello", "World", "Goodbye", "World")
* scala> val expectedResult = NonEmptyMap.of("goodbye" -> 1, "hello" -> 1, "world" -> 2)
* scala> val result = nec.groupMapReduceWith(_.trim.toLowerCase)(_ => 1)(_ + _)
@@ -545,7 +576,7 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
*
* {{{
* scala> import cats.data.{NonEmptyChain, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nec = NonEmptyChain("Hello", "World", "Goodbye", "World")
* scala> val expectedResult = NonEmptyMap.of("goodbye" -> 1, "hello" -> 1, "world" -> 2)
* scala> val result = nec.groupMapReduceWithNem(_.trim.toLowerCase)(_ => 1)(_ + _)
@@ -572,7 +603,10 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
* Remove duplicates. Duplicates are checked using `Order[_]` instance.
*/
final def distinct[AA >: A](implicit O: Order[AA]): NonEmptyChain[AA] =
- create(toChain.distinct[AA])
+ distinctBy(identity[AA])
+
+ final def distinctBy[B](f: A => B)(implicit O: Order[B]): NonEmptyChain[A] =
+ create(toChain.distinctBy[B](f))
final def sortBy[B](f: A => B)(implicit B: Order[B]): NonEmptyChain[A] = create(toChain.sortBy(f))
final def sorted[AA >: A](implicit AA: Order[AA]): NonEmptyChain[AA] = create(toChain.sorted[AA])
@@ -586,10 +620,20 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A])
sealed abstract private[data] class NonEmptyChainInstances extends NonEmptyChainInstances1 {
- implicit val catsDataInstancesForNonEmptyChain: SemigroupK[NonEmptyChain]
- with NonEmptyTraverse[NonEmptyChain]
- with Bimonad[NonEmptyChain]
- with Align[NonEmptyChain] =
+ @deprecated(
+ "maintained for the sake of binary compatibility only, use catsDataInstancesForNonEmptyChainBinCompat1 instead",
+ "2.9.0"
+ )
+ def catsDataInstancesForNonEmptyChain
+ : SemigroupK[NonEmptyChain] & NonEmptyTraverse[NonEmptyChain] & Bimonad[NonEmptyChain] & Align[
+ NonEmptyChain
+ ] =
+ catsDataInstancesForNonEmptyChainBinCompat1
+
+ implicit val catsDataInstancesForNonEmptyChainBinCompat1
+ : Align[NonEmptyChain] & Bimonad[NonEmptyChain] & NonEmptyAlternative[NonEmptyChain] & NonEmptyTraverse[
+ NonEmptyChain
+ ] =
new AbstractNonEmptyInstances[Chain, NonEmptyChain] with Align[NonEmptyChain] {
def extract[A](fa: NonEmptyChain[A]): A = fa.head
@@ -602,6 +646,18 @@ sealed abstract private[data] class NonEmptyChainInstances extends NonEmptyChain
loop(fa.head, fa.tail).value
}
+ override def mapAccumulate[S, A, B](init: S, fa: NonEmptyChain[A])(f: (S, A) => (S, B)): (S, NonEmptyChain[B]) =
+ StaticMethods.mapAccumulateFromStrictFunctor(init, fa, f)(this)
+
+ override def mapWithIndex[A, B](fa: NonEmptyChain[A])(f: (A, Int) => B): NonEmptyChain[B] =
+ StaticMethods.mapWithIndexFromStrictFunctor(fa, f)(this)
+
+ override def mapWithLongIndex[A, B](fa: NonEmptyChain[A])(f: (A, Long) => B): NonEmptyChain[B] =
+ StaticMethods.mapWithLongIndexFromStrictFunctor(fa, f)(this)
+
+ override def zipWithIndex[A](fa: NonEmptyChain[A]): NonEmptyChain[(A, Int)] =
+ fa.zipWithIndex
+
override def size[A](fa: NonEmptyChain[A]): Long = fa.length
override def reduceLeft[A](fa: NonEmptyChain[A])(f: (A, A) => A): A =
@@ -639,9 +695,7 @@ sealed abstract private[data] class NonEmptyChainInstances extends NonEmptyChain
implicit def catsDataSemigroupForNonEmptyChain[A]: Semigroup[NonEmptyChain[A]] =
Semigroup[Chain[A]].asInstanceOf[Semigroup[NonEmptyChain[A]]]
- implicit def catsDataShowForNonEmptyChain[A](implicit A: Show[A]): Show[NonEmptyChain[A]] =
- Show.show[NonEmptyChain[A]](_.show)
-
+ implicit def catsDataShowForNonEmptyChain[A: Show]: Show[NonEmptyChain[A]] = _.show
}
sealed abstract private[data] class NonEmptyChainInstances1 extends NonEmptyChainInstances2 {
diff --git a/core/src/main/scala/cats/data/NonEmptyCollection.scala b/core/src/main/scala/cats/data/NonEmptyCollection.scala
index 5c8e4d5622..6debb0e055 100644
--- a/core/src/main/scala/cats/data/NonEmptyCollection.scala
+++ b/core/src/main/scala/cats/data/NonEmptyCollection.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.data
import cats.Show
@@ -19,6 +40,7 @@ private[cats] trait NonEmptyCollection[+A, U[+_], NE[+_]] extends Any {
def filter(f: A => Boolean): U[A]
def filterNot(p: A => Boolean): U[A]
def collect[B](pf: PartialFunction[A, B]): U[B]
+ def collectFirst[B](pf: PartialFunction[A, B]): Option[B]
def find(p: A => Boolean): Option[A]
def exists(p: A => Boolean): Boolean
def forall(p: A => Boolean): Boolean
@@ -30,6 +52,7 @@ private[cats] trait NonEmptyCollection[+A, U[+_], NE[+_]] extends Any {
def zipWithIndex: NE[(A, Int)]
def distinct[AA >: A](implicit O: Order[AA]): NE[AA]
+ def distinctBy[B](f: A => B)(implicit O: Order[B]): NE[A]
def sortBy[B](f: A => B)(implicit B: Order[B]): NE[A]
def sorted[AA >: A](implicit AA: Order[AA]): NE[AA]
def groupByNem[B](f: A => B)(implicit B: Order[B]): NonEmptyMap[B, NE[A]]
diff --git a/core/src/main/scala/cats/data/NonEmptyList.scala b/core/src/main/scala/cats/data/NonEmptyList.scala
index 62612e5f29..aae4265fdf 100644
--- a/core/src/main/scala/cats/data/NonEmptyList.scala
+++ b/core/src/main/scala/cats/data/NonEmptyList.scala
@@ -1,7 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
import cats.data.NonEmptyList.ZipNonEmptyList
+import cats.instances.StaticMethods
import scala.annotation.tailrec
import scala.collection.immutable.{SortedMap, TreeMap, TreeSet}
@@ -34,7 +56,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
* res0: Int = 5
* }}}
*/
- def last: A = tail.lastOption.getOrElse(head)
+ def last: A = if (tail.isEmpty) head else tail.last
/**
* Selects all elements except the last
@@ -111,6 +133,37 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
def prepend[AA >: A](a: AA): NonEmptyList[AA] =
NonEmptyList(a, head :: tail)
+ /**
+ * Alias for [[prependList]]
+ *
+ * {{{
+ * scala> import cats.data.NonEmptyList
+ * scala> val nel = NonEmptyList.of(1, 2, 3)
+ * scala> val list = List(-1, 0)
+ * scala> list ++: nel
+ * res0: cats.data.NonEmptyList[Int] = NonEmptyList(-1, 0, 1, 2, 3)
+ * }}}
+ */
+ def ++:[AA >: A](other: List[AA]): NonEmptyList[AA] =
+ prependList(other)
+
+ /**
+ * Prepend another `List`
+ *
+ * {{{
+ * scala> import cats.data.NonEmptyList
+ * scala> val nel = NonEmptyList.of(1, 2, 3)
+ * scala> val list = List(-1, 0)
+ * scala> nel.prependList(list)
+ * res0: cats.data.NonEmptyList[Int] = NonEmptyList(-1, 0, 1, 2, 3)
+ * }}}
+ */
+ def prependList[AA >: A](other: List[AA]): NonEmptyList[AA] =
+ other match {
+ case Nil => this
+ case head :: tail => NonEmptyList(head, tail ::: toList)
+ }
+
/**
* Alias for append
*
@@ -127,6 +180,19 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
def append[AA >: A](a: AA): NonEmptyList[AA] =
NonEmptyList(head, tail :+ a)
+ /**
+ * Alias for [[concat]]
+ *
+ * {{{
+ * scala> import cats.data.NonEmptyList
+ * scala> val nel = NonEmptyList.of(1, 2, 3)
+ * scala> nel.appendList(List(4, 5))
+ * res0: cats.data.NonEmptyList[Int] = NonEmptyList(1, 2, 3, 4, 5)
+ * }}}
+ */
+ def appendList[AA >: A](other: List[AA]): NonEmptyList[AA] =
+ concat(other)
+
/**
* Alias for concatNel
*
@@ -195,6 +261,16 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
tail.collect(pf)
}
+ /**
+ * Find the first element matching the partial function, if one exists
+ */
+ def collectFirst[B](pf: PartialFunction[A, B]): Option[B] =
+ if (pf.isDefinedAt(head)) {
+ Some(pf.apply(head))
+ } else {
+ tail.collectFirst(pf)
+ }
+
/**
* Find the first element matching the predicate, if one exists
*/
@@ -264,14 +340,17 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
/**
* Remove duplicates. Duplicates are checked using `Order[_]` instance.
*/
- def distinct[AA >: A](implicit O: Order[AA]): NonEmptyList[AA] = {
- implicit val ord: Ordering[AA] = O.toOrdering
+ override def distinct[AA >: A](implicit O: Order[AA]): NonEmptyList[AA] = distinctBy(identity[AA])
+
+ override def distinctBy[B](f: A => B)(implicit O: Order[B]): NonEmptyList[A] = {
+ implicit val ord: Ordering[B] = O.toOrdering
- val buf = ListBuffer.empty[AA]
- tail.foldLeft(TreeSet(head: AA)) { (elementsSoFar, b) =>
+ val buf = ListBuffer.empty[A]
+ tail.foldLeft(TreeSet(f(head): B)) { (elementsSoFar, a) =>
+ val b = f(a)
if (elementsSoFar(b)) elementsSoFar
else {
- buf += b; elementsSoFar + b
+ buf += a; elementsSoFar + b
}
}
@@ -394,7 +473,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.NonEmptyList
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyList.of(12, -2, 3, -5)
* scala> val expectedResult = SortedMap(false -> NonEmptyList.of(-2, -5), true -> NonEmptyList.of(12, 3))
* scala> val result = nel.groupBy(_ >= 0)
@@ -411,7 +490,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
*
* {{{
* scala> import cats.data.{NonEmptyList, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyList.of(12, -2, 3, -5)
* scala> val expectedResult = NonEmptyMap.of(false -> NonEmptyList.of(-2, -5), true -> NonEmptyList.of(12, 3))
* scala> val result = nel.groupByNem(_ >= 0)
@@ -431,7 +510,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.NonEmptyList
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyList.of(12, -2, 3, -5)
* scala> val expectedResult = SortedMap(false -> NonEmptyList.of("-2", "-5"), true -> NonEmptyList.of("12", "3"))
* scala> val result = nel.groupMap(_ >= 0)(_.toString)
@@ -465,7 +544,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
*
* {{{
* scala> import cats.data.{NonEmptyList, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyList.of(12, -2, 3, -5)
* scala> val expectedResult = NonEmptyMap.of(false -> NonEmptyList.of("-2", "-5"), true -> NonEmptyList.of("12", "3"))
* scala> val result = nel.groupMapNem(_ >= 0)(_.toString)
@@ -487,7 +566,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.NonEmptyList
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyList.of("Hello", "World", "Goodbye", "World")
* scala> val expectedResult = SortedMap("goodbye" -> 1, "hello" -> 1, "world" -> 2)
* scala> val result = nel.groupMapReduce(_.trim.toLowerCase)(_ => 1)
@@ -508,7 +587,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
*
* {{{
* scala> import cats.data.{NonEmptyList, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyList.of("Hello", "World", "Goodbye", "World")
* scala> val expectedResult = NonEmptyMap.of("goodbye" -> 1, "hello" -> 1, "world" -> 2)
* scala> val result = nel.groupMapReduceNem(_.trim.toLowerCase)(_ => 1)
@@ -530,7 +609,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.NonEmptyList
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyList.of("Hello", "World", "Goodbye", "World")
* scala> val expectedResult = SortedMap("goodbye" -> 1, "hello" -> 1, "world" -> 2)
* scala> val result = nel.groupMapReduceWith(_.trim.toLowerCase)(_ => 1)(_ + _)
@@ -564,7 +643,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
*
* {{{
* scala> import cats.data.{NonEmptyList, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyList.of("Hello", "World", "Goodbye", "World")
* scala> val expectedResult = NonEmptyMap.of("goodbye" -> 1, "hello" -> 1, "world" -> 2)
* scala> val result = nel.groupMapReduceWithNem(_.trim.toLowerCase)(_ => 1)(_ + _)
@@ -582,7 +661,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
*
* {{{
* scala> import cats.data.NonEmptyList
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyList.of(12, -2, 3, -5)
* scala> val expectedResult = List(NonEmptyList.of(12, -2), NonEmptyList.of(3, -5))
* scala> val result = nel.grouped(2)
@@ -599,7 +678,7 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) extends NonEmptyCollec
* Creates new `NonEmptyMap`, similarly to List#toMap from scala standard library.
* {{{
* scala> import cats.data.{NonEmptyList, NonEmptyMap}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyList((0, "a"), List((1, "b"),(0, "c"), (2, "d")))
* scala> val expectedResult = NonEmptyMap.of(0 -> "c", 1 -> "b", 2 -> "d")
* scala> val result = nel.toNem
@@ -712,16 +791,26 @@ object NonEmptyList extends NonEmptyListInstances {
sealed abstract private[data] class NonEmptyListInstances extends NonEmptyListInstances0 {
+ @deprecated(
+ "maintained for the sake of binary compatibility only - use catsDataInstancesForNonEmptyListBinCompat1 instead",
+ "2.9.0"
+ )
+ def catsDataInstancesForNonEmptyList
+ : SemigroupK[NonEmptyList] & Bimonad[NonEmptyList] & NonEmptyTraverse[NonEmptyList] & Align[NonEmptyList] =
+ catsDataInstancesForNonEmptyListBinCompat1
+
/**
* This is not a bug. The declared type of `catsDataInstancesForNonEmptyList` intentionally ignores
* `NonEmptyReducible` trait for it not being a typeclass.
*
* Also see the discussion: PR #3541 and issue #3069.
*/
- implicit val catsDataInstancesForNonEmptyList
- : SemigroupK[NonEmptyList] with Bimonad[NonEmptyList] with NonEmptyTraverse[NonEmptyList] with Align[NonEmptyList] =
+ implicit val catsDataInstancesForNonEmptyListBinCompat1
+ : NonEmptyAlternative[NonEmptyList] & Bimonad[NonEmptyList] & NonEmptyTraverse[NonEmptyList] & Align[
+ NonEmptyList
+ ] =
new NonEmptyReducible[NonEmptyList, List]
- with SemigroupK[NonEmptyList]
+ with NonEmptyAlternative[NonEmptyList]
with Bimonad[NonEmptyList]
with NonEmptyTraverse[NonEmptyList]
with Align[NonEmptyList] {
@@ -729,6 +818,12 @@ sealed abstract private[data] class NonEmptyListInstances extends NonEmptyListIn
def combineK[A](a: NonEmptyList[A], b: NonEmptyList[A]): NonEmptyList[A] =
a.concatNel(b)
+ override def prependK[A](a: A, fa: NonEmptyList[A]): NonEmptyList[A] =
+ fa.prepend(a)
+
+ override def appendK[A](fa: NonEmptyList[A], a: A): NonEmptyList[A] =
+ fa.append(a)
+
override def split[A](fa: NonEmptyList[A]): (A, List[A]) = (fa.head, fa.tail)
override def reduceLeft[A](fa: NonEmptyList[A])(f: (A, A) => A): A =
@@ -766,6 +861,18 @@ sealed abstract private[data] class NonEmptyListInstances extends NonEmptyListIn
)(f: A => G[B])(implicit G: Applicative[G]): G[NonEmptyList[B]] =
fa.traverse(f)
+ override def mapAccumulate[S, A, B](init: S, fa: NonEmptyList[A])(f: (S, A) => (S, B)): (S, NonEmptyList[B]) =
+ StaticMethods.mapAccumulateFromStrictFunctor(init, fa, f)(this)
+
+ override def mapWithIndex[A, B](fa: NonEmptyList[A])(f: (A, Int) => B): NonEmptyList[B] =
+ StaticMethods.mapWithIndexFromStrictFunctor(fa, f)(this)
+
+ override def mapWithLongIndex[A, B](fa: NonEmptyList[A])(f: (A, Long) => B): NonEmptyList[B] =
+ StaticMethods.mapWithLongIndexFromStrictFunctor(fa, f)(this)
+
+ override def zipWithIndex[A](fa: NonEmptyList[A]): NonEmptyList[(A, Int)] =
+ fa.zipWithIndex
+
override def foldLeft[A, B](fa: NonEmptyList[A], b: B)(f: (B, A) => B): B =
fa.foldLeft(b)(f)
@@ -853,8 +960,7 @@ sealed abstract private[data] class NonEmptyListInstances extends NonEmptyListIn
}
- implicit def catsDataShowForNonEmptyList[A](implicit A: Show[A]): Show[NonEmptyList[A]] =
- Show.show[NonEmptyList[A]](_.show)
+ implicit def catsDataShowForNonEmptyList[A: Show]: Show[NonEmptyList[A]] = _.show
implicit def catsDataSemigroupForNonEmptyList[A]: Semigroup[NonEmptyList[A]] =
SemigroupK[NonEmptyList].algebra[A]
@@ -868,7 +974,7 @@ sealed abstract private[data] class NonEmptyListInstances extends NonEmptyListIn
new NonEmptyParallel[NonEmptyList] {
type F[x] = ZipNonEmptyList[x]
- def flatMap: FlatMap[NonEmptyList] = NonEmptyList.catsDataInstancesForNonEmptyList
+ def flatMap: FlatMap[NonEmptyList] = NonEmptyList.catsDataInstancesForNonEmptyListBinCompat1
def apply: Apply[ZipNonEmptyList] = ZipNonEmptyList.catsDataCommutativeApplyForZipNonEmptyList
diff --git a/core/src/main/scala/cats/data/NonEmptyMapImpl.scala b/core/src/main/scala/cats/data/NonEmptyMapImpl.scala
index 903b320e1b..7b5bcb3d6f 100644
--- a/core/src/main/scala/cats/data/NonEmptyMapImpl.scala
+++ b/core/src/main/scala/cats/data/NonEmptyMapImpl.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -5,7 +26,14 @@ import cats.kernel._
import scala.collection.immutable._
-private[data] object NonEmptyMapImpl extends NonEmptyMapInstances with Newtype2 {
+/**
+ * Actual implementation for [[cats.data.NonEmptyMap]]
+ *
+ * @note This object is kept public for the sake of binary compatibility only
+ * and therefore is subject to changes in future versions of Cats.
+ * Do not use directly - use [[cats.data.NonEmptyMap]] instead.
+ */
+object NonEmptyMapImpl extends NonEmptyMapInstances with Newtype2 {
private[data] def create[K, A](m: SortedMap[K, A]): Type[K, A] =
m.asInstanceOf[Type[K, A]]
@@ -42,7 +70,7 @@ private[data] object NonEmptyMapImpl extends NonEmptyMapInstances with Newtype2
}
-sealed class NonEmptyMapOps[K, A](val value: NonEmptyMap[K, A]) {
+sealed class NonEmptyMapOps[K, A](private[data] val value: NonEmptyMap[K, A]) {
/**
* Converts this map to a `SortedMap`.
@@ -268,7 +296,7 @@ sealed class NonEmptyMapOps[K, A](val value: NonEmptyMap[K, A]) {
sealed abstract private[data] class NonEmptyMapInstances extends NonEmptyMapInstances0 {
implicit def catsDataInstancesForNonEmptyMap[K]
- : SemigroupK[NonEmptyMap[K, *]] with NonEmptyTraverse[NonEmptyMap[K, *]] with Align[NonEmptyMap[K, *]] =
+ : SemigroupK[NonEmptyMap[K, *]] & NonEmptyTraverse[NonEmptyMap[K, *]] & Align[NonEmptyMap[K, *]] =
new SemigroupK[NonEmptyMap[K, *]] with NonEmptyTraverse[NonEmptyMap[K, *]] with Align[NonEmptyMap[K, *]] {
override def map[A, B](fa: NonEmptyMap[K, A])(f: A => B): NonEmptyMap[K, B] =
@@ -326,7 +354,7 @@ sealed abstract private[data] class NonEmptyMapInstances extends NonEmptyMapInst
@deprecated("Use catsDataInstancesForNonEmptyMap override without Order", "2.2.0-M3")
def catsDataInstancesForNonEmptyMap[K](
orderK: Order[K]
- ): SemigroupK[NonEmptyMap[K, *]] with NonEmptyTraverse[NonEmptyMap[K, *]] with Align[NonEmptyMap[K, *]] =
+ ): SemigroupK[NonEmptyMap[K, *]] & NonEmptyTraverse[NonEmptyMap[K, *]] & Align[NonEmptyMap[K, *]] =
catsDataInstancesForNonEmptyMap[K]
implicit def catsDataHashForNonEmptyMap[K: Hash, A: Hash]: Hash[NonEmptyMap[K, A]] =
@@ -336,22 +364,13 @@ sealed abstract private[data] class NonEmptyMapInstances extends NonEmptyMapInst
def catsDataHashForNonEmptyMap[K, A](hashK: Hash[K], orderK: Order[K], hashA: Hash[A]): Hash[NonEmptyMap[K, A]] =
catsDataHashForNonEmptyMap(hashK, hashA)
- implicit def catsDataShowForNonEmptyMap[K: Show, A: Show]: Show[NonEmptyMap[K, A]] =
- Show.show[NonEmptyMap[K, A]](_.show)
+ implicit def catsDataShowForNonEmptyMap[K: Show, A: Show]: Show[NonEmptyMap[K, A]] = _.show
@deprecated("Use catsDataSemigroupForNonEmptyMap", "2.5.0")
- def catsDataBandForNonEmptyMap[K, A]: Band[NonEmptyMap[K, A]] =
- new Band[NonEmptyMap[K, A]] {
- def combine(x: NonEmptyMap[K, A], y: NonEmptyMap[K, A]): NonEmptyMap[K, A] = x ++ y
- }
+ def catsDataBandForNonEmptyMap[K, A]: Band[NonEmptyMap[K, A]] = _ ++ _
implicit def catsDataSemigroupForNonEmptyMap[K, A: Semigroup]: Semigroup[NonEmptyMap[K, A]] =
- new Semigroup[NonEmptyMap[K, A]] {
- def combine(x: NonEmptyMap[K, A], y: NonEmptyMap[K, A]): NonEmptyMap[K, A] =
- NonEmptyMap.fromMapUnsafe(
- Semigroup[SortedMap[K, A]].combine(x.toSortedMap, y.toSortedMap)
- )
- }
+ (x, y) => NonEmptyMap.fromMapUnsafe(Semigroup[SortedMap[K, A]].combine(x.toSortedMap, y.toSortedMap))
}
sealed abstract private[data] class NonEmptyMapInstances0 {
diff --git a/core/src/main/scala/cats/data/NonEmptySeq.scala b/core/src/main/scala/cats/data/NonEmptySeq.scala
index d15542d0d5..457a14b26e 100644
--- a/core/src/main/scala/cats/data/NonEmptySeq.scala
+++ b/core/src/main/scala/cats/data/NonEmptySeq.scala
@@ -1,12 +1,33 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
import cats.data.NonEmptySeq.ZipNonEmptySeq
+import cats.kernel.compat.scalaVersionSpecific._
import scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.immutable.{Seq, SortedMap, TreeMap, TreeSet}
-import kernel.compat.scalaVersionSpecific._
/**
* A data type which represents a `Seq` guaranteed to contain at least one element.
@@ -76,6 +97,8 @@ final class NonEmptySeq[+A] private (val toSeq: Seq[A]) extends AnyVal with NonE
def collect[B](pf: PartialFunction[A, B]): Seq[B] = toSeq.collect(pf)
+ def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = toSeq.collectFirst(pf)
+
/**
* Alias for [[concat]]
*/
@@ -98,6 +121,11 @@ final class NonEmptySeq[+A] private (val toSeq: Seq[A]) extends AnyVal with NonE
*/
def concat[AA >: A](other: Seq[AA]): NonEmptySeq[AA] = new NonEmptySeq(toSeq ++ other)
+ /**
+ * Append another `Seq` to this, producing a new `NonEmptySeq`.
+ */
+ def appendSeq[AA >: A](other: Seq[AA]): NonEmptySeq[AA] = concat(other)
+
/**
* Append another `NonEmptySeq` to this, producing a new `NonEmptySeq`.
*/
@@ -199,23 +227,26 @@ final class NonEmptySeq[+A] private (val toSeq: Seq[A]) extends AnyVal with NonE
* universal .toString method.
*/
def show[AA >: A](implicit AA: Show[AA]): String =
- s"NonEmptySeq(${toSeq.map(Show[AA].show).mkString(", ")})"
+ s"NonEmptySeq(${toSeq.iterator.map(AA.show).mkString(", ")})"
def length: Int = toSeq.length
- override def toString: String = s"NonEmptySeq(${toSeq.map(_.toString).mkString(", ")})"
+ override def toString: String = s"NonEmptySeq(${toSeq.iterator.map(_.toString).mkString(", ")})"
/**
* Remove duplicates. Duplicates are checked using `Order[_]` instance.
*/
- def distinct[AA >: A](implicit O: Order[AA]): NonEmptySeq[AA] = {
- implicit val ord: Ordering[AA] = O.toOrdering
+ override def distinct[AA >: A](implicit O: Order[AA]): NonEmptySeq[AA] = distinctBy(identity[AA])
+
+ override def distinctBy[B](f: A => B)(implicit O: Order[B]): NonEmptySeq[A] = {
+ implicit val ord: Ordering[B] = O.toOrdering
- val buf = Seq.newBuilder[AA]
- tail.foldLeft(TreeSet(head: AA)) { (elementsSoFar, a) =>
- if (elementsSoFar(a)) elementsSoFar
+ val buf = Seq.newBuilder[A]
+ tail.foldLeft(TreeSet(f(head): B)) { (elementsSoFar, a) =>
+ val b = f(a)
+ if (elementsSoFar(b)) elementsSoFar
else {
- buf += a; elementsSoFar + a
+ buf += a; elementsSoFar + b
}
}
@@ -239,6 +270,23 @@ final class NonEmptySeq[+A] private (val toSeq: Seq[A]) extends AnyVal with NonE
def reverse: NonEmptySeq[A] =
new NonEmptySeq(toSeq.reverse)
+ /**
+ * Zips this `NonEmptySeq` with another `NonEmptySeq` and returns the pairs of elements.
+ *
+ * {{{
+ * scala> import cats.data.NonEmptySeq
+ * scala> val as = NonEmptySeq.of(1, 2, 3)
+ * scala> val bs = NonEmptySeq.of("A", "B", "C")
+ * scala> as.zip(bs)
+ * res0: cats.data.NonEmptySeq[(Int, String)] = NonEmptySeq((1,A), (2,B), (3,C))
+ * }}}
+ */
+ def zip[B](nes: NonEmptySeq[B]): NonEmptySeq[(A, B)] =
+ NonEmptySeq((head, nes.head), tail.zip(nes.tail))
+
+ def mapWithIndex[B](f: (A, Int) => B): NonEmptySeq[B] =
+ new NonEmptySeq(toSeq.zipWithIndex.map(ai => f(ai._1, ai._2)))
+
def zipWithIndex: NonEmptySeq[(A, Int)] =
new NonEmptySeq(toSeq.zipWithIndex)
@@ -255,7 +303,7 @@ final class NonEmptySeq[+A] private (val toSeq: Seq[A]) extends AnyVal with NonE
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.NonEmptySeq
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val neSeq = NonEmptySeq.of(12, -2, 3, -5)
* scala> val expectedResult = SortedMap(false -> NonEmptySeq.of(-2, -5), true -> NonEmptySeq.of(12, 3))
* scala> val result = neSeq.groupBy(_ >= 0)
@@ -287,7 +335,7 @@ final class NonEmptySeq[+A] private (val toSeq: Seq[A]) extends AnyVal with NonE
*
* {{{
* scala> import cats.data.{NonEmptyMap, NonEmptySeq}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptySeq.of(12, -2, 3, -5)
* scala> val expectedResult = NonEmptyMap.of(false -> NonEmptySeq.of(-2, -5), true -> NonEmptySeq.of(12, 3))
* scala> val result = nel.groupByNem(_ >= 0)
@@ -303,7 +351,7 @@ final class NonEmptySeq[+A] private (val toSeq: Seq[A]) extends AnyVal with NonE
*
* {{{
* scala> import cats.data.NonEmptySeq
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptySeq.of(12, -2, 3, -5)
* scala> val expectedResult = List(NonEmptySeq.of(12, -2), NonEmptySeq.of(3, -5))
* scala> val result = nel.grouped(2)
@@ -320,7 +368,7 @@ final class NonEmptySeq[+A] private (val toSeq: Seq[A]) extends AnyVal with NonE
* Creates new `NonEmptyMap`, similarly to List#toMap from scala standard library.
* {{{
* scala> import cats.data.{NonEmptyMap, NonEmptySeq}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import scala.collection.immutable.Seq
* scala> val neSeq = NonEmptySeq((0, "a"), Seq((1, "b"),(0, "c"), (2, "d")))
* scala> val expectedResult = NonEmptyMap.of(0 -> "c", 1 -> "b", 2 -> "d")
@@ -350,16 +398,24 @@ final class NonEmptySeq[+A] private (val toSeq: Seq[A]) extends AnyVal with NonE
@suppressUnusedImportWarningForScalaVersionSpecific
sealed abstract private[data] class NonEmptySeqInstances {
+ @deprecated(
+ "maintained for the sake of binary compatibility only - use catsDataInstancesForNonEmptySeqBinCompat1 instead",
+ "2.9.0"
+ )
+ def catsDataInstancesForNonEmptySeq
+ : SemigroupK[NonEmptySeq] & Bimonad[NonEmptySeq] & NonEmptyTraverse[NonEmptySeq] & Align[NonEmptySeq] =
+ catsDataInstancesForNonEmptySeqBinCompat1
+
/**
* This is not a bug. The declared type of `catsDataInstancesForNonEmptySeq` intentionally ignores
* `NonEmptyReducible` trait for it not being a typeclass.
*
* Also see the discussion: PR #3541 and issue #3069.
*/
- implicit val catsDataInstancesForNonEmptySeq
- : SemigroupK[NonEmptySeq] with Bimonad[NonEmptySeq] with NonEmptyTraverse[NonEmptySeq] with Align[NonEmptySeq] =
+ implicit val catsDataInstancesForNonEmptySeqBinCompat1
+ : NonEmptyAlternative[NonEmptySeq] & Bimonad[NonEmptySeq] & NonEmptyTraverse[NonEmptySeq] & Align[NonEmptySeq] =
new NonEmptyReducible[NonEmptySeq, Seq]
- with SemigroupK[NonEmptySeq]
+ with NonEmptyAlternative[NonEmptySeq]
with Bimonad[NonEmptySeq]
with NonEmptyTraverse[NonEmptySeq]
with Align[NonEmptySeq] {
@@ -367,6 +423,12 @@ sealed abstract private[data] class NonEmptySeqInstances {
def combineK[A](a: NonEmptySeq[A], b: NonEmptySeq[A]): NonEmptySeq[A] =
a.concatNeSeq(b)
+ override def prependK[A](a: A, fa: NonEmptySeq[A]): NonEmptySeq[A] =
+ fa.prepend(a)
+
+ override def appendK[A](fa: NonEmptySeq[A], a: A): NonEmptySeq[A] =
+ fa.append(a)
+
override def split[A](fa: NonEmptySeq[A]): (A, Seq[A]) = (fa.head, fa.tail)
override def size[A](fa: NonEmptySeq[A]): Long = fa.length.toLong
@@ -413,6 +475,9 @@ sealed abstract private[data] class NonEmptySeqInstances {
)(f: (A) => G[B])(implicit G: Applicative[G]): G[NonEmptySeq[B]] =
G.map2Eval(f(fa.head), Always(Traverse[Seq].traverse(fa.tail)(f)))(NonEmptySeq(_, _)).value
+ override def mapWithIndex[A, B](fa: NonEmptySeq[A])(f: (A, Int) => B): NonEmptySeq[B] =
+ fa.mapWithIndex(f)
+
override def zipWithIndex[A](fa: NonEmptySeq[A]): NonEmptySeq[(A, Int)] =
fa.zipWithIndex
@@ -493,23 +558,19 @@ sealed abstract private[data] class NonEmptySeqInstances {
NonEmptySeq.fromSeqUnsafe(Align[Seq].alignWith(fa.toSeq, fb.toSeq)(f))
}
- implicit def catsDataEqForNonEmptySeq[A](implicit A: Eq[A]): Eq[NonEmptySeq[A]] =
- new Eq[NonEmptySeq[A]] {
- def eqv(x: NonEmptySeq[A], y: NonEmptySeq[A]): Boolean = x === y
- }
+ implicit def catsDataEqForNonEmptySeq[A: Eq]: Eq[NonEmptySeq[A]] = _ === _
- implicit def catsDataShowForNonEmptySeq[A](implicit A: Show[A]): Show[NonEmptySeq[A]] =
- Show.show[NonEmptySeq[A]](_.show)
+ implicit def catsDataShowForNonEmptySeq[A: Show]: Show[NonEmptySeq[A]] = _.show
implicit def catsDataSemigroupForNonEmptySeq[A]: Semigroup[NonEmptySeq[A]] =
- catsDataInstancesForNonEmptySeq.algebra
+ catsDataInstancesForNonEmptySeqBinCompat1.algebra
implicit def catsDataParallelForNonEmptySeq: NonEmptyParallel.Aux[NonEmptySeq, ZipNonEmptySeq] =
new NonEmptyParallel[NonEmptySeq] {
type F[x] = ZipNonEmptySeq[x]
def apply: Apply[ZipNonEmptySeq] = ZipNonEmptySeq.catsDataCommutativeApplyForZipNonEmptySeq
- def flatMap: FlatMap[NonEmptySeq] = NonEmptySeq.catsDataInstancesForNonEmptySeq
+ def flatMap: FlatMap[NonEmptySeq] = NonEmptySeq.catsDataInstancesForNonEmptySeqBinCompat1
def sequential: ZipNonEmptySeq ~> NonEmptySeq =
new (ZipNonEmptySeq ~> NonEmptySeq) { def apply[A](a: ZipNonEmptySeq[A]): NonEmptySeq[A] = a.value }
diff --git a/core/src/main/scala/cats/data/NonEmptySet.scala b/core/src/main/scala/cats/data/NonEmptySet.scala
index 0fc3328ebe..b0c2279aef 100644
--- a/core/src/main/scala/cats/data/NonEmptySet.scala
+++ b/core/src/main/scala/cats/data/NonEmptySet.scala
@@ -1,12 +1,41 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
import cats.kernel._
import scala.collection.immutable._
+
import kernel.compat.scalaVersionSpecific._
-private[data] object NonEmptySetImpl extends NonEmptySetInstances with Newtype {
+/**
+ * Actual implementation for [[cats.data.NonEmptySet]]
+ *
+ * @note This object is kept public for the sake of binary compatibility only
+ * and therefore is subject to changes in future versions of Cats.
+ * Do not use directly - use [[cats.data.NonEmptySet]] instead.
+ */
+object NonEmptySetImpl extends NonEmptySetInstances with Newtype {
private[data] def create[A](s: SortedSet[A]): Type[A] =
s.asInstanceOf[Type[A]]
@@ -33,7 +62,7 @@ private[data] object NonEmptySetImpl extends NonEmptySetInstances with Newtype {
}
@suppressUnusedImportWarningForScalaVersionSpecific
-sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
+sealed class NonEmptySetOps[A](private[data] val value: NonEmptySet[A]) {
implicit private val ordering: Ordering[A] = toSortedSet.ordering
implicit private val order: Order[A] = Order.fromOrdering
@@ -52,7 +81,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
* Alias for [[union]]
* {{{
* scala> import cats.data.NonEmptySet
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nes = NonEmptySet.of(1, 2, 4, 5)
* scala> nes ++ NonEmptySet.of(1, 2, 7)
* res0: cats.data.NonEmptySet[Int] = TreeSet(1, 2, 4, 5, 7)
@@ -64,7 +93,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
* Alias for [[union]]
* {{{
* scala> import cats.data.NonEmptySet
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nes = NonEmptySet.of(1, 2, 4, 5)
* scala> nes | NonEmptySet.of(1, 2, 7)
* res0: cats.data.NonEmptySet[Int] = TreeSet(1, 2, 4, 5, 7)
@@ -76,7 +105,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
* Alias for [[diff]]
* {{{
* scala> import cats.data.NonEmptySet
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nes = NonEmptySet.of(1, 2, 4, 5)
* scala> nes -- NonEmptySet.of(1, 2, 7)
* res0: scala.collection.immutable.SortedSet[Int] = TreeSet(4, 5)
@@ -88,7 +117,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
* Alias for [[diff]]
* {{{
* scala> import cats.data.NonEmptySet
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nes = NonEmptySet.of(1, 2, 4, 5)
* scala> nes &~ NonEmptySet.of(1, 2, 7)
* res0: scala.collection.immutable.SortedSet[Int] = TreeSet(4, 5)
@@ -100,7 +129,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
* Alias for [[intersect]]
* {{{
* scala> import cats.data.NonEmptySet
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nes = NonEmptySet.of(1, 2, 4, 5)
* scala> nes & NonEmptySet.of(1, 2, 7)
* res0: scala.collection.immutable.SortedSet[Int] = TreeSet(1, 2)
@@ -125,7 +154,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
* Converts this set to a `NonEmptyList`.
* {{{
* scala> import cats.data.NonEmptySet
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nes = NonEmptySet.of(1, 2, 3, 4, 5)
* scala> nes.toNonEmptyList
* res0: cats.data.NonEmptyList[Int] = NonEmptyList(1, 2, 3, 4, 5)
@@ -152,7 +181,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
* Alias for [[contains]]
* {{{
* scala> import cats.data.NonEmptySet
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nes = NonEmptySet.of(1, 2, 3, 4, 5)
* scala> nes(3)
* res0: Boolean = true
@@ -268,7 +297,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
* Map a function over all the elements of this set and concatenate the resulting sets into one.
* {{{
* scala> import cats.data.NonEmptySet
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nes = NonEmptySet.of(1, 2, 3)
* scala> nes.concatMap(n => NonEmptySet.of(n, n * 4, n * 5))
* res0: cats.data.NonEmptySet[Int] = TreeSet(1, 2, 3, 4, 5, 8, 10, 12, 15)
@@ -310,7 +339,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
*
* {{{
* scala> import cats.data.NonEmptySet
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val as = NonEmptySet.of(1, 2, 3)
* scala> val bs = NonEmptySet.of("A", "B", "C")
* scala> as.zipWith(bs)(_.toString + _)
@@ -319,7 +348,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
*/
def zipWith[B, C](b: NonEmptySet[B])(f: (A, B) => C)(implicit C: Order[C]): NonEmptySet[C] = {
implicit val cOrdering: Ordering[C] = C.toOrdering
- NonEmptySetImpl.create((toSortedSet.lazyZip(b.toSortedSet)).map(f))
+ NonEmptySetImpl.create(toSortedSet.lazyZip(b.toSortedSet).map(f))
}
/**
@@ -344,7 +373,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) {
}
sealed abstract private[data] class NonEmptySetInstances extends NonEmptySetInstances0 {
- implicit val catsDataInstancesForNonEmptySet: SemigroupK[NonEmptySet] with Reducible[NonEmptySet] =
+ implicit val catsDataInstancesForNonEmptySet: SemigroupK[NonEmptySet] & Reducible[NonEmptySet] =
new SemigroupK[NonEmptySet] with Reducible[NonEmptySet] {
def combineK[A](a: NonEmptySet[A], b: NonEmptySet[A]): NonEmptySet[A] =
@@ -397,8 +426,7 @@ sealed abstract private[data] class NonEmptySetInstances extends NonEmptySetInst
implicit override def A0: Order[A] = A
}
- implicit def catsDataShowForNonEmptySet[A](implicit A: Show[A]): Show[NonEmptySet[A]] =
- Show.show[NonEmptySet[A]](_.show)
+ implicit def catsDataShowForNonEmptySet[A: Show]: Show[NonEmptySet[A]] = _.show
implicit def catsDataSemilatticeForNonEmptySet[A]: Semilattice[NonEmptySet[A]] =
new Semilattice[NonEmptySet[A]] {
@@ -412,7 +440,8 @@ sealed abstract private[data] class NonEmptySetInstances0 extends NonEmptySetIns
}
sealed abstract private[data] class NonEmptySetInstances1 {
- private[data] def catsDataEqForNonEmptySet[A](implicit A: Order[A]): Eq[NonEmptySet[A]] =
+ @deprecated("use catsDataEqForNonEmptySetFromEqA instead", "2.8.0")
+ def catsDataEqForNonEmptySet[A](implicit A: Order[A]): Eq[NonEmptySet[A]] =
catsDataEqForNonEmptySetFromEqA[A]
implicit def catsDataEqForNonEmptySetFromEqA[A](implicit A: Eq[A]): Eq[NonEmptySet[A]] =
diff --git a/core/src/main/scala/cats/data/NonEmptyVector.scala b/core/src/main/scala/cats/data/NonEmptyVector.scala
index bdc9e139e3..7dffe88ce3 100644
--- a/core/src/main/scala/cats/data/NonEmptyVector.scala
+++ b/core/src/main/scala/cats/data/NonEmptyVector.scala
@@ -1,12 +1,34 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
import cats.data.NonEmptyVector.ZipNonEmptyVector
+import cats.instances.StaticMethods
+import cats.kernel.compat.scalaVersionSpecific._
import scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.immutable.{SortedMap, TreeMap, TreeSet, VectorBuilder}
-import kernel.compat.scalaVersionSpecific._
/**
* A data type which represents a `Vector` guaranteed to contain at least one element.
@@ -78,6 +100,8 @@ final class NonEmptyVector[+A] private (val toVector: Vector[A])
def collect[B](pf: PartialFunction[A, B]): Vector[B] = toVector.collect(pf)
+ def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = toVector.collectFirst(pf)
+
/**
* Alias for [[concat]]
*/
@@ -100,6 +124,18 @@ final class NonEmptyVector[+A] private (val toVector: Vector[A])
*/
def concat[AA >: A](other: Vector[AA]): NonEmptyVector[AA] = new NonEmptyVector(toVector ++ other)
+ /**
+ * Append another `Vector` to this, producing a new `NonEmptyVector`
+ *
+ * {{{
+ * scala> import cats.data.NonEmptyVector
+ * scala> val nev = NonEmptyVector.of(1, 2, 3)
+ * scala> nev.appendVector(Vector(4, 5))
+ * res0: cats.data.NonEmptyVector[Int] = NonEmptyVector(1, 2, 3, 4, 5)
+ * }}}
+ */
+ def appendVector[AA >: A](other: Vector[AA]): NonEmptyVector[AA] = concat(other)
+
/**
* Append another `NonEmptyVector` to this, producing a new `NonEmptyVector`.
*/
@@ -210,14 +246,17 @@ final class NonEmptyVector[+A] private (val toVector: Vector[A])
/**
* Remove duplicates. Duplicates are checked using `Order[_]` instance.
*/
- def distinct[AA >: A](implicit O: Order[AA]): NonEmptyVector[AA] = {
- implicit val ord: Ordering[AA] = O.toOrdering
+ override def distinct[AA >: A](implicit O: Order[AA]): NonEmptyVector[AA] = distinctBy(identity[AA])
+
+ override def distinctBy[B](f: A => B)(implicit O: Order[B]): NonEmptyVector[A] = {
+ implicit val ord: Ordering[B] = O.toOrdering
- val buf = Vector.newBuilder[AA]
- tail.foldLeft(TreeSet(head: AA)) { (elementsSoFar, a) =>
- if (elementsSoFar(a)) elementsSoFar
+ val buf = Vector.newBuilder[A]
+ tail.foldLeft(TreeSet(f(head): B)) { (elementsSoFar, a) =>
+ val b = f(a)
+ if (elementsSoFar(b)) elementsSoFar
else {
- buf += a; elementsSoFar + a
+ buf += a; elementsSoFar + b
}
}
@@ -257,7 +296,7 @@ final class NonEmptyVector[+A] private (val toVector: Vector[A])
* {{{
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.data.NonEmptyVector
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nev = NonEmptyVector.of(12, -2, 3, -5)
* scala> val expectedResult = SortedMap(false -> NonEmptyVector.of(-2, -5), true -> NonEmptyVector.of(12, 3))
* scala> val result = nev.groupBy(_ >= 0)
@@ -289,7 +328,7 @@ final class NonEmptyVector[+A] private (val toVector: Vector[A])
*
* {{{
* scala> import cats.data.{NonEmptyMap, NonEmptyVector}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyVector.of(12, -2, 3, -5)
* scala> val expectedResult = NonEmptyMap.of(false -> NonEmptyVector.of(-2, -5), true -> NonEmptyVector.of(12, 3))
* scala> val result = nel.groupByNem(_ >= 0)
@@ -305,7 +344,7 @@ final class NonEmptyVector[+A] private (val toVector: Vector[A])
*
* {{{
* scala> import cats.data.NonEmptyVector
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nel = NonEmptyVector.of(12, -2, 3, -5)
* scala> val expectedResult = List(NonEmptyVector.of(12, -2), NonEmptyVector.of(3, -5))
* scala> val result = nel.grouped(2)
@@ -322,7 +361,7 @@ final class NonEmptyVector[+A] private (val toVector: Vector[A])
* Creates new `NonEmptyMap`, similarly to List#toMap from scala standard library.
* {{{
* scala> import cats.data.{NonEmptyMap, NonEmptyVector}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val nev = NonEmptyVector((0, "a"), Vector((1, "b"),(0, "c"), (2, "d")))
* scala> val expectedResult = NonEmptyMap.of(0 -> "c", 1 -> "b", 2 -> "d")
* scala> val result = nev.toNem
@@ -348,7 +387,15 @@ final class NonEmptyVector[+A] private (val toVector: Vector[A])
}
@suppressUnusedImportWarningForScalaVersionSpecific
-sealed abstract private[data] class NonEmptyVectorInstances {
+sealed abstract private[data] class NonEmptyVectorInstances extends NonEmptyVectorInstances0 {
+
+ @deprecated(
+ "maintained for the sake of binary compatibility only - use catsDataInstancesForNonEmptyChainBinCompat1 instead",
+ "2.9.0"
+ )
+ def catsDataInstancesForNonEmptyVector
+ : SemigroupK[NonEmptyVector] & Bimonad[NonEmptyVector] & NonEmptyTraverse[NonEmptyVector] & Align[NonEmptyVector] =
+ catsDataInstancesForNonEmptyVectorBinCompat1
/**
* This is not a bug. The declared type of `catsDataInstancesForNonEmptyVector` intentionally ignores
@@ -356,12 +403,12 @@ sealed abstract private[data] class NonEmptyVectorInstances {
*
* Also see the discussion: PR #3541 and issue #3069.
*/
- implicit val catsDataInstancesForNonEmptyVector: SemigroupK[NonEmptyVector]
- with Bimonad[NonEmptyVector]
- with NonEmptyTraverse[NonEmptyVector]
- with Align[NonEmptyVector] =
+ implicit val catsDataInstancesForNonEmptyVectorBinCompat1
+ : NonEmptyAlternative[NonEmptyVector] & Bimonad[NonEmptyVector] & NonEmptyTraverse[NonEmptyVector] & Align[
+ NonEmptyVector
+ ] =
new NonEmptyReducible[NonEmptyVector, Vector]
- with SemigroupK[NonEmptyVector]
+ with NonEmptyAlternative[NonEmptyVector]
with Bimonad[NonEmptyVector]
with NonEmptyTraverse[NonEmptyVector]
with Align[NonEmptyVector] {
@@ -369,6 +416,12 @@ sealed abstract private[data] class NonEmptyVectorInstances {
def combineK[A](a: NonEmptyVector[A], b: NonEmptyVector[A]): NonEmptyVector[A] =
a.concatNev(b)
+ override def prependK[A](a: A, fa: NonEmptyVector[A]): NonEmptyVector[A] =
+ fa.prepend(a)
+
+ override def appendK[A](fa: NonEmptyVector[A], a: A): NonEmptyVector[A] =
+ fa.append(a)
+
override def split[A](fa: NonEmptyVector[A]): (A, Vector[A]) = (fa.head, fa.tail)
override def size[A](fa: NonEmptyVector[A]): Long = fa.length.toLong
@@ -415,9 +468,23 @@ sealed abstract private[data] class NonEmptyVectorInstances {
)(f: (A) => G[B])(implicit G: Applicative[G]): G[NonEmptyVector[B]] =
G.map2Eval(f(fa.head), Always(Traverse[Vector].traverse(fa.tail)(f)))(NonEmptyVector(_, _)).value
+ override def mapAccumulate[S, A, B](init: S, fa: NonEmptyVector[A])(
+ f: (S, A) => (S, B)
+ ): (S, NonEmptyVector[B]) =
+ StaticMethods.mapAccumulateFromStrictFunctor(init, fa, f)(this)
+
+ override def mapWithLongIndex[A, B](fa: NonEmptyVector[A])(f: (A, Long) => B): NonEmptyVector[B] =
+ StaticMethods.mapWithLongIndexFromStrictFunctor(fa, f)(this)
+
+ override def mapWithIndex[A, B](fa: NonEmptyVector[A])(f: (A, Int) => B): NonEmptyVector[B] =
+ StaticMethods.mapWithIndexFromStrictFunctor(fa, f)(this)
+
override def zipWithIndex[A](fa: NonEmptyVector[A]): NonEmptyVector[(A, Int)] =
fa.zipWithIndex
+ override def updated_[A, B >: A](fa: NonEmptyVector[A], idx: Long, b: B): Option[NonEmptyVector[B]] =
+ Traverse[Vector].updated_(fa.toVector, idx, b).map(NonEmptyVector.fromVectorUnsafe)
+
override def foldLeft[A, B](fa: NonEmptyVector[A], b: B)(f: (B, A) => B): B =
fa.foldLeft(b)(f)
@@ -495,23 +562,23 @@ sealed abstract private[data] class NonEmptyVectorInstances {
NonEmptyVector.fromVectorUnsafe(Align[Vector].alignWith(fa.toVector, fb.toVector)(f))
}
- implicit def catsDataEqForNonEmptyVector[A](implicit A: Eq[A]): Eq[NonEmptyVector[A]] =
- new Eq[NonEmptyVector[A]] {
- def eqv(x: NonEmptyVector[A], y: NonEmptyVector[A]): Boolean = x === y
+ implicit def catsDataOrderForNonEmptyVector[A: Order]: Order[NonEmptyVector[A]] =
+ new Order[NonEmptyVector[A]] {
+ override def compare(x: NonEmptyVector[A], y: NonEmptyVector[A]): Int =
+ Order[Vector[A]].compare(x.toVector, y.toVector)
}
- implicit def catsDataShowForNonEmptyVector[A](implicit A: Show[A]): Show[NonEmptyVector[A]] =
- Show.show[NonEmptyVector[A]](_.show)
+ implicit def catsDataShowForNonEmptyVector[A: Show]: Show[NonEmptyVector[A]] = _.show
implicit def catsDataSemigroupForNonEmptyVector[A]: Semigroup[NonEmptyVector[A]] =
- catsDataInstancesForNonEmptyVector.algebra
+ catsDataInstancesForNonEmptyVectorBinCompat1.algebra
implicit def catsDataParallelForNonEmptyVector: NonEmptyParallel.Aux[NonEmptyVector, ZipNonEmptyVector] =
new NonEmptyParallel[NonEmptyVector] {
type F[x] = ZipNonEmptyVector[x]
def apply: Apply[ZipNonEmptyVector] = ZipNonEmptyVector.catsDataCommutativeApplyForZipNonEmptyVector
- def flatMap: FlatMap[NonEmptyVector] = NonEmptyVector.catsDataInstancesForNonEmptyVector
+ def flatMap: FlatMap[NonEmptyVector] = NonEmptyVector.catsDataInstancesForNonEmptyVectorBinCompat1
def sequential: ZipNonEmptyVector ~> NonEmptyVector =
new (ZipNonEmptyVector ~> NonEmptyVector) { def apply[A](a: ZipNonEmptyVector[A]): NonEmptyVector[A] = a.value }
@@ -572,3 +639,17 @@ object NonEmptyVector extends NonEmptyVectorInstances with Serializable {
implicit def catsDataEqForZipNonEmptyVector[A: Eq]: Eq[ZipNonEmptyVector[A]] = Eq.by(_.value)
}
}
+
+sealed abstract private[data] class NonEmptyVectorInstances0 extends NonEmptyVectorInstances1 {
+ implicit def catsDataPartialOrderForNonEmptyVector[A: PartialOrder]: PartialOrder[NonEmptyVector[A]] =
+ PartialOrder.by[NonEmptyVector[A], Vector[A]](_.toVector)
+}
+
+sealed abstract private[data] class NonEmptyVectorInstances1 extends NonEmptyVectorInstances2 {
+ implicit def catsDataHashForNonEmptyVector[A: Hash]: Hash[NonEmptyVector[A]] =
+ Hash.by(_.toVector)
+}
+
+sealed abstract private[data] class NonEmptyVectorInstances2 {
+ implicit def catsDataEqForNonEmptyVector[A: Eq]: Eq[NonEmptyVector[A]] = _ === _
+}
diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala
index e6f0762b43..5e3c390fd1 100644
--- a/core/src/main/scala/cats/data/OneAnd.scala
+++ b/core/src/main/scala/cats/data/OneAnd.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -19,7 +40,7 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) {
* Combine the head and tail into a single `F[A]` value.
*/
def unwrap(implicit F: Alternative[F]): F[A] =
- F.combineK(F.pure(head), tail)
+ F.prependK(head, tail)
/**
* remove elements not matching the predicate
@@ -33,7 +54,7 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) {
* Append another OneAnd to this
*/
def combine(other: OneAnd[F, A])(implicit F: Alternative[F]): OneAnd[F, A] =
- OneAnd(head, F.combineK(tail, F.combineK(F.pure(other.head), other.tail)))
+ OneAnd(head, F.combineK(tail, other.unwrap))
/**
* find the first element matching the predicate, if one exists
@@ -126,13 +147,16 @@ sealed abstract private[data] class OneAndInstances extends OneAndLowPriority0 {
}
- implicit def catsDataEqForOneAnd[A, F[_]](implicit A: Eq[A], FA: Eq[F[A]]): Eq[OneAnd[F, A]] =
- new Eq[OneAnd[F, A]] {
- def eqv(x: OneAnd[F, A], y: OneAnd[F, A]): Boolean = x === y
+ implicit def catsDataOrderForOneAnd[A, F[_]](implicit A: Order[A], FA: Order[F[A]]): Order[OneAnd[F, A]] =
+ new Order[OneAnd[F, A]] {
+ def compare(x: OneAnd[F, A], y: OneAnd[F, A]): Int =
+ A.compare(x.head, y.head) match {
+ case 0 => FA.compare(x.tail, y.tail)
+ case neq => neq
+ }
}
- implicit def catsDataShowForOneAnd[A, F[_]](implicit A: Show[A], FA: Show[F[A]]): Show[OneAnd[F, A]] =
- Show.show[OneAnd[F, A]](_.show)
+ implicit def catsDataShowForOneAnd[A, F[_]](implicit A: Show[A], FA: Show[F[A]]): Show[OneAnd[F, A]] = _.show
implicit def catsDataSemigroupKForOneAnd[F[_]: Alternative]: SemigroupK[OneAnd[F, *]] =
new SemigroupK[OneAnd[F, *]] {
@@ -222,7 +246,7 @@ sealed abstract private[data] class OneAndLowPriority2 extends OneAndLowPriority
override def ap[A, B](ff: OneAnd[F, A => B])(fa: OneAnd[F, A]): OneAnd[F, B] = {
val (f, tf) = (ff.head, ff.tail)
val (a, ta) = (fa.head, fa.tail)
- val fb = F.ap(tf)(F.combineK(F.pure(a), ta))
+ val fb = F.ap(tf)(F.prependK(a, ta))
OneAnd(f(a), F.combineK(F.map(ta)(f), fb))
}
}
@@ -236,6 +260,12 @@ sealed abstract private[data] class OneAndLowPriority1 extends OneAndLowPriority
def traverse[G[_], A, B](fa: OneAnd[F, A])(f: (A) => G[B])(implicit G: Applicative[G]): G[OneAnd[F, B]] =
G.map2Eval(f(fa.head), Always(F.traverse(fa.tail)(f)))(OneAnd(_, _)).value
+ override def mapAccumulate[S, A, B](init: S, fa: OneAnd[F, A])(f: (S, A) => (S, B)): (S, OneAnd[F, B]) = {
+ val (s1, b) = f(init, fa.head)
+ val (s2, fb) = F.mapAccumulate(s1, fa.tail)(f)
+ (s2, OneAnd(b, fb))
+ }
+
def foldLeft[A, B](fa: OneAnd[F, A], b: B)(f: (B, A) => B): B =
fa.foldLeft(b)(f)
@@ -245,6 +275,9 @@ sealed abstract private[data] class OneAndLowPriority1 extends OneAndLowPriority
}
sealed abstract private[data] class OneAndLowPriority0_5 extends OneAndLowPriority1 {
+
+ implicit def catsDataEqForOneAnd[A, F[_]](implicit A: Eq[A], FA: Eq[F[A]]): Eq[OneAnd[F, A]] = _ === _
+
implicit def catsDataReducibleForOneAnd[F[_]](implicit F: Foldable[F]): Reducible[OneAnd[F, *]] =
new NonEmptyReducible[OneAnd[F, *], F] {
override def split[A](fa: OneAnd[F, A]): (A, F[A]) = (fa.head, fa.tail)
@@ -257,6 +290,20 @@ sealed abstract private[data] class OneAndLowPriority0_5 extends OneAndLowPriori
}
sealed abstract private[data] class OneAndLowPriority0 extends OneAndLowPriority0_5 {
+
+ implicit def catsDataPartialOrderForOneAnd[A, F[_]](implicit
+ A: PartialOrder[A],
+ FA: PartialOrder[F[A]]
+ ): PartialOrder[OneAnd[F, A]] =
+ new PartialOrder[OneAnd[F, A]] {
+ def partialCompare(x: OneAnd[F, A], y: OneAnd[F, A]): Double = {
+ A.partialCompare(x.head, y.head) match {
+ case 0.0 => FA.partialCompare(x.tail, y.tail)
+ case neq => neq
+ }
+ }
+ }
+
implicit def catsDataNonEmptyTraverseForOneAnd[F[_]](implicit
F: Traverse[F],
F2: Alternative[F]
diff --git a/core/src/main/scala/cats/data/Op.scala b/core/src/main/scala/cats/data/Op.scala
index 1ad065656c..bb341bc536 100644
--- a/core/src/main/scala/cats/data/Op.scala
+++ b/core/src/main/scala/cats/data/Op.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala/cats/data/OptionT.scala b/core/src/main/scala/cats/data/OptionT.scala
index 8609fe3db4..d16a09ba94 100644
--- a/core/src/main/scala/cats/data/OptionT.scala
+++ b/core/src/main/scala/cats/data/OptionT.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -19,7 +40,6 @@ final case class OptionT[F[_], A](value: F[Option[A]]) {
*
* Example:
* {{{
- * scala> import cats.implicits._
* scala> import cats.data.OptionT
*
* scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(23), None))
@@ -41,6 +61,15 @@ final case class OptionT[F[_], A](value: F[Option[A]]) {
* Catamorphism on the Option. This is identical to [[fold]], but it only has
* one parameter list, which can result in better type inference in some
* contexts.
+ *
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(42), None))
+ * scala> optionT.cata[String]("default", x => x.toString + "!")
+ * res0: List[String] = List(42!, default)
+ * }}}
*/
def cata[B](default: => B, f: A => B)(implicit F: Functor[F]): F[B] =
fold(default)(f)
@@ -49,18 +78,59 @@ final case class OptionT[F[_], A](value: F[Option[A]]) {
* Effectful catamorphism on the Option. This is identical to [[foldF]], but it only has
* one parameter list, which can result in better type inference in some
* contexts.
+ *
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(42), None))
+ * scala> optionT.cataF[String](Nil, x => List(x.toString + "!"))
+ * res0: List[String] = List(42!)
+ * }}}
*/
def cataF[B](default: => F[B], f: A => F[B])(implicit F: FlatMap[F]): F[B] =
foldF(default)(f)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ * scala> optionT.map(_.toString + "!")
+ * res0: OptionT[List, String] = OptionT(List(Some(2!), None, Some(414!), None, None))
+ * }}}
+ */
def map[B](f: A => B)(implicit F: Functor[F]): OptionT[F, B] =
OptionT(F.map(value)(_.map(f)))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT.some[List](99)
+ * scala> optionT.imap[Char](_.toChar)(_.toInt)
+ * res0: OptionT[List, Char] = OptionT(List(Some(c)))
+ * }}}
+ */
def imap[B](f: A => B)(g: B => A)(implicit F: Invariant[F]): OptionT[F, B] =
OptionT {
F.imap(value)(_.map(f))(_.map(g))
}
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.Show
+ * scala> import cats.data.OptionT
+ *
+ * scala> val showIntOption: Show[Option[Int]] = oi => oi.map(_.toString + "!").getOrElse("default")
+ * scala> val optionT: OptionT[Show, Int] = OptionT[Show, Int](showIntOption)
+ * scala> optionT.contramap[Double](_.toInt).value.show(Some(5.4321))
+ * res0: String = 5!
+ * }}}
+ */
def contramap[B](f: B => A)(implicit F: Contravariant[F]): OptionT[F, B] =
OptionT {
F.contramap(value)(_.map(f))
@@ -68,108 +138,518 @@ final case class OptionT[F[_], A](value: F[Option[A]]) {
/**
* Modify the context `F` using transformation `f`.
+ *
+ * Example:
+ * {{{
+ * scala> import cats.~>
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionToList: Option ~> List = new ~>[Option, List] { override def apply[A](o: Option[A]): List[A] = o.toList }
+ * scala> val optionT: OptionT[Option, Int] = OptionT.some(42)
+ * scala> optionT.mapK[List](optionToList)
+ * res0: OptionT[List, Int] = OptionT(List(Some(42)))
+ * }}}
*/
def mapK[G[_]](f: F ~> G): OptionT[G, A] = OptionT[G, A](f(value))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(3), Some(5)))
+ * scala> optionT.semiflatMap(x => List(x, x * 6))
+ * res0: OptionT[List, Int] = OptionT(List(Some(3), Some(18), Some(5), Some(30)))
+ * }}}
+ */
def semiflatMap[B](f: A => F[B])(implicit F: Monad[F]): OptionT[F, B] =
flatMap(a => OptionT.liftF(f(a)))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[Either[String, *], Int] = OptionT.some[Either[String, *]](3)
+ * scala> optionT.semiflatTap { case 1 | 2 | 3 => Right("hit!"); case _ => Left("miss!") }
+ * res0: OptionT[Either[String, *], Int] = OptionT(Right(Some(3)))
+ * scala> optionT.semiflatTap { case 0 | 1 | 2 => Right("hit!"); case _ => Left("miss!") }
+ * res1: OptionT[Either[String, *], Int] = OptionT(Left(miss!))
+ * }}}
+ */
def semiflatTap[B](f: A => F[B])(implicit F: Monad[F]): OptionT[F, A] =
semiflatMap(a => F.as(f(a), a))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(2), Some(3), Some(4)))
+ * scala> optionT.mapFilter(x => Option(x).filter(_ % 2 == 0))
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * }}}
+ */
def mapFilter[B](f: A => Option[B])(implicit F: Functor[F]): OptionT[F, B] =
subflatMap(f)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(2), Some(3), Some(4)))
+ * scala> optionT.flatMap(x => OptionT.when(x % 2 == 0)(x))
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * }}}
+ */
def flatMap[B](f: A => OptionT[F, B])(implicit F: Monad[F]): OptionT[F, B] =
flatMapF(a => f(a).value)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(2), Some(3), Some(4)))
+ * scala> optionT.flatMapF(x => List(Option(x).filter(_ % 2 == 0)))
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * }}}
+ */
def flatMapF[B](f: A => F[Option[B]])(implicit F: Monad[F]): OptionT[F, B] =
OptionT(F.flatMap(value)(_.fold(F.pure[Option[B]](None))(f)))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(2), Some(3), Some(4)))
+ * scala> optionT.flatTransform(x => List(x.filter(_ % 2 == 0)))
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * }}}
+ */
def flatTransform[B](f: Option[A] => F[Option[B]])(implicit F: Monad[F]): OptionT[F, B] =
OptionT(F.flatMap(value)(f))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(2), Some(3), Some(4)))
+ * scala> optionT.transform(_.filter(_ % 2 == 0))
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * }}}
+ */
def transform[B](f: Option[A] => Option[B])(implicit F: Functor[F]): OptionT[F, B] =
OptionT(F.map(value)(f))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(2), Some(3), Some(4)))
+ * scala> optionT.subflatMap(x => Option(x).filter(_ % 2 == 0))
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * }}}
+ */
def subflatMap[B](f: A => Option[B])(implicit F: Functor[F]): OptionT[F, B] =
transform(_.flatMap(f))
/**
* Perform an effect if the value inside the is a `None`, leaving the value untouched. Equivalent to [[orElseF]]
* with an effect returning `None` as argument.
+ *
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> // prints "no value"
+ * scala> val optionT: OptionT[Either[String, *], Int] = OptionT[Either[String, *], Int](Right(None))
+ * scala> optionT.flatTapNone(Left("no value!"))
+ * res0: OptionT[Either[String, *], Int] = OptionT(Left(no value!))
+ * }}}
*/
def flatTapNone[B](ifNone: => F[B])(implicit F: Monad[F]): OptionT[F, A] =
OptionT(F.flatTap(value)(_.fold(F.void(ifNone))(_ => F.unit)))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(2), None, Some(4)))
+ * scala> optionT.getOrElse(42)
+ * res0: List[Int] = List(2, 42, 4)
+ * }}}
+ */
def getOrElse[B >: A](default: => B)(implicit F: Functor[F]): F[B] =
F.map(value)(_.getOrElse(default))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(2), None, Some(4)))
+ * scala> optionT.getOrElseF(List(42))
+ * res0: List[Int] = List(2, 42, 4)
+ * }}}
+ */
def getOrElseF[B >: A](default: => F[B])(implicit F: Monad[F]): F[B] =
F.flatMap(value)(_.fold(default)(F.pure))
+ /**
+ * Like [[getOrElseF]] but accept an error `E` and raise it when the inner `Option` is `None`
+ *
+ * Equivalent to `getOrElseF(F.raiseError(e)))`
+ *
+ * {{{
+ * scala> import cats.data.OptionT
+ * scala> import scala.util.{Success, Try}
+ *
+ * scala> val optionT: OptionT[Try, Int] = OptionT[Try, Int](Success(None))
+ * scala> optionT.getOrRaise(new RuntimeException("ERROR!"))
+ * res0: Try[Int] = Failure(java.lang.RuntimeException: ERROR!)
+ * }}}
+ */
+ def getOrRaise[E](e: => E)(implicit F: MonadError[F, ? >: E]): F[A] =
+ getOrElseF(F.raiseError(e))
+
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ * scala> optionT.collect{ case i if i == 2 => i }
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), None, None, None, None))
+ * scala> optionT.collect{ case i: Int => i == 2 }
+ * res0: OptionT[List, Boolean] = OptionT(List(Some(true), None, Some(false), None, None))
+ * }}}
+ */
def collect[B](f: PartialFunction[A, B])(implicit F: Functor[F]): OptionT[F, B] =
OptionT(F.map(value)(_.collect(f)))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(2), None, Some(3)))
+ * scala> optionT.exists(_ % 2 == 0)
+ * res0: List[Boolean] = List(true, false, false)
+ * }}}
+ */
def exists(f: A => Boolean)(implicit F: Functor[F]): F[Boolean] =
F.map(value)(_.exists(f))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ * scala> optionT.filter(el => (el % 2 == 0))
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ *
+ * scala> optionT.filter(el => (el % 3 == 0))
+ * res1: OptionT[List, Int] = OptionT(List(None, None, Some(414), None, None))
+ * }}}
+ */
def filter(p: A => Boolean)(implicit F: Functor[F]): OptionT[F, A] =
OptionT(F.map(value)(_.filter(p)))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(100), None, Some(421), Some(333)))
+ * scala> optionT.filterF(n => List(n % 100 == 0, n.toString.toSet.size == 1))
+ *
+ * res0: OptionT[List, Int] = OptionT(List(Some(100), None, None, None, None, None, Some(333)))
+ * }}}
+ */
+ def filterF(p: A => F[Boolean])(implicit F: Monad[F]): OptionT[F, A] =
+ OptionT(F.flatMap(value) {
+ case v @ Some(a) => F.map(p(a)) { if (_) v else None }
+ case None => F.pure(None)
+ })
+
+ /**
+ * It is used for desugaring 'for comprehensions'. OptionT wouldn't work in 'for-comprehensions' without
+ * this method.
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ * scala> optionT.withFilter(el => (el % 2 == 0))
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ *
+ * scala> optionT.withFilter(el => (el % 3 == 0))
+ * res1: OptionT[List, Int] = OptionT(List(None, None, Some(414), None, None))
+ * }}}
+ */
def withFilter(p: A => Boolean)(implicit F: Functor[F]): OptionT[F, A] =
filter(p)(F)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ * scala> optionT.filterNot(el => (el % 2 == 0))
+ * res0: OptionT[List, Int] = OptionT(List(None, None, None, None, None))
+ *
+ * scala> optionT.filterNot(el => (el % 3 == 0))
+ * res1: OptionT[List, Int] = OptionT(List(Some(2), None, None, None, None))
+ * }}}
+ */
def filterNot(p: A => Boolean)(implicit F: Functor[F]): OptionT[F, A] =
OptionT(F.map(value)(_.filterNot(p)))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT[List, Int](List(Some(2), None, Some(3)))
+ * scala> optionT.forall(_ % 2 == 0)
+ * res0: List[Boolean] = List(true, true, false)
+ * }}}
+ */
def forall(f: A => Boolean)(implicit F: Functor[F]): F[Boolean] =
F.map(value)(_.forall(f))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ * scala> optionT.isDefined
+ * res0: List[Boolean] = List(true, false, true, false, false)
+ * }}}
+ */
def isDefined(implicit F: Functor[F]): F[Boolean] =
F.map(value)(_.isDefined)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ * scala> optionT.isEmpty
+ * res0: List[Boolean] = List(false, true, false, true, true)
+ * }}}
+ */
def isEmpty(implicit F: Functor[F]): F[Boolean] =
F.map(value)(_.isEmpty)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ * scala> optionT.orElseF(List[Option[Int]](Some(-1)))
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), Some(-1), Some(414), Some(-1), Some(-1)))
+ * }}}
+ */
def orElse(default: => OptionT[F, A])(implicit F: Monad[F]): OptionT[F, A] =
orElseF(default.value)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * scala> optionT.orElseF(List(Some(3)))
+ * res0: OptionT[List, Int] = OptionT(List(Some(2), Some(3), Some(4)))
+ * }}}
+ */
def orElseF(default: => F[Option[A]])(implicit F: Monad[F]): OptionT[F, A] =
OptionT(F.flatMap(value) {
case s @ Some(_) => F.pure(s)
case None => default
})
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.EitherT
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * scala> optionT.toRight[Int](3)
+ * res0: EitherT[List, Int, Int] = EitherT(List(Right(2), Left(3), Right(4)))
+ * }}}
+ */
def toRight[L](left: => L)(implicit F: Functor[F]): EitherT[F, L, A] =
EitherT(cata(Left(left), Right.apply))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.EitherT
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * scala> optionT.toRightF[Int](List(3))
+ * res0: EitherT[List, Int, Int] = EitherT(List(Right(2), Left(3), Right(4)))
+ * }}}
+ */
def toRightF[L](left: => F[L])(implicit F: Monad[F]): EitherT[F, L, A] =
EitherT(cataF(F.map(left)(Left.apply[L, A]), a => F.pure(Right(a))))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.EitherT
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * scala> optionT.toLeft[Int](3)
+ * res0: EitherT[List, Int, Int] = EitherT(List(Left(2), Right(3), Left(4)))
+ * }}}
+ */
def toLeft[R](right: => R)(implicit F: Functor[F]): EitherT[F, A, R] =
EitherT(cata(Right(right), Left.apply))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.EitherT
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(4)))
+ * scala> optionT.toLeftF[Int](List(3))
+ * res0: EitherT[List, Int, Int] = EitherT(List(Left(2), Right(3), Left(4)))
+ * }}}
+ */
def toLeftF[R](right: => F[R])(implicit F: Monad[F]): EitherT[F, A, R] =
EitherT(cataF(F.map(right)(Right.apply[A, R]), a => F.pure(Left(a))))
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ * scala> optionT.show
+ * res0: String = List(Some(2), None, Some(414), None, None)
+ * }}}
+ */
def show(implicit F: Show[F[Option[A]]]): String = F.show(value)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(414), None, None))
+ * scala> optionT.compare(OptionT[List, Int](List(Some(2))))
+ * res0: Int = 1
+ *
+ * scala> optionT.compare(OptionT[List, Int](List(Some(2), None, Some(414), None, None)))
+ * res0: Int = 0
+ * }}}
+ */
def compare(that: OptionT[F, A])(implicit o: Order[F[Option[A]]]): Int =
o.compare(value, that.value)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Double] = OptionT(List(Some(0.1), None, Some(0.5)))
+ * scala> optionT.partialCompare(OptionT[List, Double](List(Some(2))))
+ * res0: Double = -1.0
+ *
+ * scala> optionT.partialCompare(OptionT[List, Double](List(Some(0.1), None, Some(0.5))))
+ * res0: Double = 0.0
+ * }}}
+ */
def partialCompare(that: OptionT[F, A])(implicit p: PartialOrder[F[Option[A]]]): Double =
p.partialCompare(value, that.value)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(5)))
+ * scala> optionT === OptionT[List, Int](List(Some(2), None))
+ * res0: Boolean = false
+ *
+ * scala> optionT === OptionT[List, Int](List(Some(2), None, Some(5)))
+ * res0: Boolean = true
+ * }}}
+ */
def ===(that: OptionT[F, A])(implicit eq: Eq[F[Option[A]]]): Boolean =
eq.eqv(value, that.value)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ * scala> import scala.util.Right
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(5)))
+ * scala> optionT.traverse[Either[Int, *], Int](x => Right[Int, Int](x))
+ * res0: Either[Int, OptionT[List, Int]] = Right(OptionT(List(Some(2), None, Some(5))))
+ * }}}
+ */
def traverse[G[_], B](f: A => G[B])(implicit F: Traverse[F], G: Applicative[G]): G[OptionT[F, B]] =
G.map(F.compose(Traverse[Option]).traverse(value)(f))(OptionT.apply)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(5)))
+ * scala> optionT.mapAccumulate(0)((s, a) => (s + a, s"$a!"))
+ * res0: (Int, OptionT[List, String]) = (7,OptionT(List(Some(2!), None, Some(5!))))
+ * }}}
+ */
+ def mapAccumulate[S, B](init: S)(f: (S, A) => (S, B))(implicit traverseF: Traverse[F]): (S, OptionT[F, B]) = {
+ val (snext, vnext) = traverseF.mapAccumulate(init, value)(Traverse[Option].mapAccumulate(_, _)(f))
+ (snext, OptionT(vnext))
+ }
+
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(5)))
+ * scala> optionT.foldLeft(0)((acc, x) => acc + x)
+ * res0: Int = 7
+ * }}}
+ */
def foldLeft[B](b: B)(f: (B, A) => B)(implicit F: Foldable[F]): B =
F.compose(Foldable[Option]).foldLeft(value, b)(f)
+ /**
+ * Example:
+ * {{{
+ * scala> import cats.Eval
+ * scala> import cats.data.OptionT
+ *
+ * scala> val optionT: OptionT[List, Int] = OptionT(List(Some(2), None, Some(5)))
+ * scala> optionT.foldRight(Eval.One)((x, acc) => Eval.later(x * acc.value)).value
+ * res0: Int = 10
+ * }}}
+ */
def foldRight[B](lb: Eval[B])(f: (A, Eval[B]) => Eval[B])(implicit F: Foldable[F]): Eval[B] =
F.compose(Foldable[Option]).foldRight(value, lb)(f)
@@ -181,8 +661,8 @@ final case class OptionT[F[_], A](value: F[Option[A]]) {
* inconsistent with the behavior of the `ap` from `Monad` of `OptionT`.
*
* {{{
- * scala> import cats.implicits._
* scala> import cats.data.OptionT
+ * scala> import cats.syntax.all._
* scala> val ff: OptionT[List, Int => String] =
* | OptionT(List(Option(_.toString), None))
* scala> val fa: OptionT[List, Int] = OptionT(List(Option(1), Option(2)))
@@ -209,7 +689,6 @@ object OptionT extends OptionTInstances {
* Creates a `OptionT[A]` from an `A`
*
* {{{
- * scala> import cats.implicits._
* scala> OptionT.pure[List](2)
* res0: OptionT[List, Int] = OptionT(List(Some(2)))
* }}}
@@ -220,7 +699,6 @@ object OptionT extends OptionTInstances {
* An alias for pure
*
* {{{
- * scala> import cats.implicits._
* scala> OptionT.some[List](2)
* res0: OptionT[List, Int] = OptionT(List(Some(2)))
* }}}
@@ -234,7 +712,6 @@ object OptionT extends OptionTInstances {
* Transforms an `Option` into an `OptionT`, lifted into the specified `Applicative`.
*
* {{{
- * scala> import cats.implicits._
* scala> val o: Option[Int] = Some(2)
* scala> OptionT.fromOption[List](o)
* res0: OptionT[List, Int] = OptionT(List(Some(2)))
@@ -258,7 +735,7 @@ object OptionT extends OptionTInstances {
/**
* Same as [[liftF]], but expressed as a FunctionK for use with mapK
* {{{
- * scala> import cats._, data._, implicits._
+ * scala> import cats._, data._, syntax.all._
* scala> val a: EitherT[Eval, String, Int] = 1.pure[EitherT[Eval, String, *]]
* scala> val b: EitherT[OptionT[Eval, *], String, Int] = a.mapK(OptionT.liftK)
* scala> b.value.value.value
@@ -282,6 +759,14 @@ object OptionT extends OptionTInstances {
def whenF[F[_], A](cond: Boolean)(fa: => F[A])(implicit F: Applicative[F]): OptionT[F, A] =
if (cond) OptionT.liftF(fa) else OptionT.none[F, A]
+ /**
+ * Creates a non-empty `OptionT[F, A]` from an `F[A]` value if the given F-condition is considered `true`.
+ * Otherwise, `none[F, A]` is returned. Analogous to `Option.when` but for effectful conditions.
+ */
+ def whenM[F[_], A](cond: F[Boolean])(fa: => F[A])(implicit F: Monad[F]): OptionT[F, A] = OptionT(
+ F.ifM(cond)(ifTrue = F.map(fa)(Some(_)), ifFalse = F.pure(None))
+ )
+
/**
* Same as `whenF`, but expressed as a FunctionK for use with mapK.
*/
@@ -302,6 +787,14 @@ object OptionT extends OptionTInstances {
def unlessF[F[_], A](cond: Boolean)(fa: => F[A])(implicit F: Applicative[F]): OptionT[F, A] =
OptionT.whenF(!cond)(fa)
+ /**
+ * Creates a non-empty `OptionT[F, A]` from an `F[A]` value if the given F-condition is considered `false`.
+ * Otherwise, `none[F, A]` is returned. Analogous to `Option.unless` but for effectful conditions.
+ */
+ def unlessM[F[_], A](cond: F[Boolean])(fa: => F[A])(implicit F: Monad[F]): OptionT[F, A] = OptionT(
+ F.ifM(cond)(ifTrue = F.pure(None), ifFalse = F.map(fa)(Some(_)))
+ )
+
/**
* Same as `unlessF`, but expressed as a FunctionK for use with mapK.
*/
@@ -535,6 +1028,9 @@ sealed private[data] trait OptionTTraverse[F[_]] extends Traverse[OptionT[F, *]]
def traverse[G[_]: Applicative, A, B](fa: OptionT[F, A])(f: A => G[B]): G[OptionT[F, B]] =
fa.traverse(f)
+
+ override def mapAccumulate[S, A, B](init: S, fa: OptionT[F, A])(f: (S, A) => (S, B)): (S, OptionT[F, B]) =
+ fa.mapAccumulate(init)(f)
}
private[data] trait OptionTSemigroup[F[_], A] extends Semigroup[OptionT[F, A]] {
diff --git a/core/src/main/scala/cats/data/RepresentableStore.scala b/core/src/main/scala/cats/data/RepresentableStore.scala
index 1eee35d96c..867e1dff40 100644
--- a/core/src/main/scala/cats/data/RepresentableStore.scala
+++ b/core/src/main/scala/cats/data/RepresentableStore.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.data
import cats.{Comonad, Functor, Representable}
diff --git a/core/src/main/scala/cats/data/RepresentableStoreT.scala b/core/src/main/scala/cats/data/RepresentableStoreT.scala
index 1e1d9ac51f..5cd2832da6 100644
--- a/core/src/main/scala/cats/data/RepresentableStoreT.scala
+++ b/core/src/main/scala/cats/data/RepresentableStoreT.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.data
import cats.{Applicative, Comonad, Functor, Monoid, Representable}
diff --git a/core/src/main/scala/cats/data/StrictConstFunction1.scala b/core/src/main/scala/cats/data/StrictConstFunction1.scala
new file mode 100644
index 0000000000..8d3b9c203b
--- /dev/null
+++ b/core/src/main/scala/cats/data/StrictConstFunction1.scala
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats
+package data
+
+/** A `Function1` with constant value and strictly evaluated combinators. Not suitable
+ * for composing with side-effecting functions. */
+final private[data] case class StrictConstFunction1[A](a: A) extends Function1[Any, A] {
+ def apply(arg: Any): A = a
+
+ /** Creates a new `StrictConstFunction1` by applying `g` to this function's constant value.
+ * `g` will not be evaluated when the resulting function is subsequently run. Not stack-safe. */
+ override def andThen[B](g: A => B): Any => B = g match {
+ case g: StrictConstFunction1[B] => g
+ case _ => StrictConstFunction1(g(a))
+ }
+
+ /** This is a no-op; `g` will never be used. */
+ override def compose[A0](g: A0 => Any): A0 => A = this
+}
diff --git a/core/src/main/scala/cats/data/Tuple2K.scala b/core/src/main/scala/cats/data/Tuple2K.scala
index 83ea5b3c91..b5a1d88f4a 100644
--- a/core/src/main/scala/cats/data/Tuple2K.scala
+++ b/core/src/main/scala/cats/data/Tuple2K.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -93,10 +114,7 @@ sealed abstract private[data] class Tuple2KInstances0 extends Tuple2KInstances1
def G: Contravariant[G] = GC
}
implicit def catsDataEqForTuple2K[F[_], G[_], A](implicit FF: Eq[F[A]], GG: Eq[G[A]]): Eq[Tuple2K[F, G, A]] =
- new Eq[Tuple2K[F, G, A]] {
- def eqv(x: Tuple2K[F, G, A], y: Tuple2K[F, G, A]): Boolean =
- FF.eqv(x.first, y.first) && GG.eqv(x.second, y.second)
- }
+ (x, y) => FF.eqv(x.first, y.first) && GG.eqv(x.second, y.second)
}
sealed abstract private[data] class Tuple2KInstances1 extends Tuple2KInstances2 {
@@ -124,7 +142,7 @@ sealed abstract private[data] class Tuple2KInstances1 extends Tuple2KInstances2
new Representable[Tuple2K[F, G, *]] {
type Representation = Either[FF.Representation, GG.Representation]
- val F = new Tuple2KFunctor[F, G] {
+ val F: Functor[Tuple2K[F, G, *]] = new Tuple2KFunctor[F, G] {
val F = FF.F
val G = GG.F
}
diff --git a/core/src/main/scala/cats/data/Validated.scala b/core/src/main/scala/cats/data/Validated.scala
index d4475fb10a..5faf9a970c 100644
--- a/core/src/main/scala/cats/data/Validated.scala
+++ b/core/src/main/scala/cats/data/Validated.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -12,7 +33,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1= "error".invalid[Option[String]]
* scala> val v2= Some("abc").valid[String]
@@ -33,7 +54,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val validated= "error".invalid[Unit]
* scala> validated.isValid
@@ -49,7 +70,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val validated= "error".invalid[Unit]
* scala> validated.isInvalid
@@ -76,7 +97,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1= "error".invalid[Int]
* scala> val v2= 123.valid[String]
@@ -98,7 +119,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
* Return the Valid value, or the result of f if Invalid
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = Some("exception").invalid[String]
* scala> val v2 = "OK".valid[Option[String]]
@@ -121,7 +142,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = List("error").invalid[Int]
* scala> val v2 = 123.valid[List[String]]
@@ -144,7 +165,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = Some("error").invalid[Int]
* scala> val v2 = 123.valid[Option[String]]
@@ -169,7 +190,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = Some("error").invalid[Int]
* scala> val v2 = 123.valid[Option[String]]
@@ -194,7 +215,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = List("error1").invalid[Int]
* scala> val v2 = 123.valid[List[String]]
@@ -226,7 +247,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -249,7 +270,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = List("error").invalid[Int]
* scala> val v2 = 123.valid[List[String]]
@@ -272,7 +293,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -296,7 +317,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = Some("error").invalid[Int]
* scala> val v2 = 123.valid[Option[String]]
@@ -319,7 +340,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -342,7 +363,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -366,7 +387,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -387,7 +408,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1: Validated[String, Int] = "error".invalid[Int]
* scala> val v2: Validated[String, Int] = 123.valid[String]
@@ -408,7 +429,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = "error2".invalid[Int]
@@ -453,7 +474,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = "error".invalid[Int]
@@ -483,7 +504,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -509,7 +530,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.ValidatedNec
*
* scala> val v1 = "error".invalidNec[Int]
@@ -541,7 +562,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -565,7 +586,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -591,7 +612,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -609,13 +630,22 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
case e @ Invalid(_) => F.pure(e)
}
+ def mapAccumulate[S, EE >: E, B](init: S)(f: (S, A) => (S, B)): (S, Validated[EE, B]) =
+ this match {
+ case Valid(a) =>
+ val (snext, b) = f(init, a)
+ (snext, Valid(b))
+
+ case e @ Invalid(_) => (init, e)
+ }
+
/**
* apply the given function to the value with the given B when
* valid, otherwise return the given B
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -639,7 +669,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.Eval
*
* scala> val v1 = "error".invalid[Int]
@@ -679,7 +709,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -706,7 +736,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalidNel[List[Int]]
* scala> val v2 = "error2".invalidNel[List[Int]]
@@ -736,7 +766,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = "error".invalid[Int]
* scala> val v2 = 123.valid[String]
@@ -757,7 +787,7 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val v1 = Seq("error").invalid[List[String]]
* scala> val v2 = List("Ok").valid[Seq[String]]
@@ -878,8 +908,8 @@ sealed abstract private[data] class ValidatedInstances extends ValidatedInstance
}
case Valid(a) =>
fb match {
- case Invalid(e) => Valid(f(Ior.left(a)))
case Valid(b) => Valid(f(Ior.both(a, b)))
+ case Invalid(_) => Valid(f(Ior.left(a)))
}
}
}
@@ -897,10 +927,7 @@ sealed abstract private[data] class ValidatedInstances extends ValidatedInstance
override def eqv(x: Validated[A, B], y: Validated[A, B]): Boolean = x === y
}
- implicit def catsDataShowForValidated[A, B](implicit A: Show[A], B: Show[B]): Show[Validated[A, B]] =
- new Show[Validated[A, B]] {
- def show(f: Validated[A, B]): String = f.show
- }
+ implicit def catsDataShowForValidated[A: Show, B: Show]: Show[Validated[A, B]] = _.show
implicit val catsDataBitraverseForValidated: Bitraverse[Validated] =
new Bitraverse[Validated] {
@@ -947,13 +974,7 @@ sealed abstract private[data] class ValidatedInstances extends ValidatedInstance
sealed abstract private[data] class ValidatedInstances1 extends ValidatedInstances2 {
- implicit def catsDataSemigroupForValidated[A, B](implicit
- A: Semigroup[A],
- B: Semigroup[B]
- ): Semigroup[Validated[A, B]] =
- new Semigroup[Validated[A, B]] {
- def combine(x: Validated[A, B], y: Validated[A, B]): Validated[A, B] = x.combine(y)
- }
+ implicit def catsDataSemigroupForValidated[A: Semigroup, B: Semigroup]: Semigroup[Validated[A, B]] = _ combine _
implicit def catsDataCommutativeApplicativeForValidated[E: CommutativeSemigroup]
: CommutativeApplicative[Validated[E, *]] =
@@ -967,10 +988,7 @@ sealed abstract private[data] class ValidatedInstances1 extends ValidatedInstanc
}
sealed abstract private[data] class ValidatedInstances2 {
- implicit def catsDataEqForValidated[A: Eq, B: Eq]: Eq[Validated[A, B]] =
- new Eq[Validated[A, B]] {
- def eqv(x: Validated[A, B], y: Validated[A, B]): Boolean = x === y
- }
+ implicit def catsDataEqForValidated[A: Eq, B: Eq]: Eq[Validated[A, B]] = _ === _
implicit def catsDataTraverseFunctorForValidated[E]: Traverse[Validated[E, *]] =
new Traverse[Validated[E, *]] {
@@ -978,6 +996,9 @@ sealed abstract private[data] class ValidatedInstances2 {
override def traverse[G[_]: Applicative, A, B](fa: Validated[E, A])(f: (A) => G[B]): G[Validated[E, B]] =
fa.traverse(f)
+ override def mapAccumulate[S, A, B](init: S, fa: Validated[E, A])(f: (S, A) => (S, B)): (S, Validated[E, B]) =
+ fa.mapAccumulate(init)(f)
+
override def foldLeft[A, B](fa: Validated[E, A], b: B)(f: (B, A) => B): B =
fa.foldLeft(b)(f)
@@ -1104,7 +1125,7 @@ private[data] trait ValidatedFunctions {
try {
valid(f)
} catch {
- case scala.util.control.NonFatal(t) => invalid(t)
+ case t if scala.util.control.NonFatal(t) => invalid(t)
}
/**
@@ -1145,6 +1166,11 @@ private[data] trait ValidatedFunctions {
*/
final def condNel[E, A](test: Boolean, a: => A, e: => E): ValidatedNel[E, A] =
if (test) validNel(a) else invalidNel(e)
+
+ /**
+ * Cached value of `Valid(())` to avoid allocations for a common case.
+ */
+ final def unit[E]: Validated[E, Unit] = Validated.validUnit
}
private[data] trait ValidatedFunctionsBinCompat0 {
diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala
index 215b08f99a..c9acca8505 100644
--- a/core/src/main/scala/cats/data/WriterT.scala
+++ b/core/src/main/scala/cats/data/WriterT.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
@@ -10,7 +31,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer = WriterT.liftF[Option, List[String], Int](Some(123))
* scala> writer.tell(List("a","b","c")).tell(List("d","e","f"))
@@ -24,7 +45,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer: WriterT[Option, List[String], Int] = WriterT.liftF(Some(123))
* scala> writer.tell(List("a","b","c")).written.getOrElse(Nil)
@@ -38,7 +59,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer: WriterT[Option, List[String], Int] = WriterT.liftF(Some(123))
* scala> val wt: WriterT[Option, List[String], Int] = writer.tell(List("error"))
@@ -55,7 +76,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer: WriterT[Option, String, Int] = WriterT.liftF(Some(123))
* scala> val wt: WriterT[Option, String, Int] = writer.tell("error").tell(" log")
@@ -74,7 +95,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer: WriterT[Option, String, Int] = WriterT.liftF(Some(123))
* scala> val wt: WriterT[Option, String, Int] = writer.tell("error")
@@ -96,7 +117,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val wr1: WriterT[Option, String, Int] = WriterT.liftF(None)
* scala> val wr2 = wr1.tell("error")
@@ -122,7 +143,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val wr1: WriterT[Option, String, Int] = WriterT.liftF(Some(123))
* scala> val wr2 = wr1.tell("log...")
@@ -142,7 +163,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* {{{
* scala> import cats.data.WriterT
* scala> import cats.arrow.FunctionK
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val optionWriter = WriterT.liftF[Option, String, Int](Some(123)).tell("log")
* res0: WriterT[Option, String, Int](Some((log,123)))
@@ -166,7 +187,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val wr1 = WriterT.liftF[Option, String, Int](Some(123)).tell("error")
* res0: WriterT[Option, String, Int] = WriterT(Some(error,123))
@@ -189,7 +210,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val wr1 = WriterT.liftF[Option, String, Int](Some(123)).tell("quack")
* res0: WriterT[Option, String, Int] = WriterT(Some(quack,123))
@@ -205,7 +226,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val wr1 = WriterT.liftF[Option, String, Int](Some(123)).tell("456")
* res0: WriterT[Option, String, Int] = WriterT(Some(456,123))
@@ -221,7 +242,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(246)).tell("error")
* res0: WriterT[Option, String, Int] = WriterT(Some((error,246)))
@@ -237,7 +258,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(123)).tell("log")
* scala> writer.swap
@@ -251,7 +272,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(123)).tell("error")
* scala> writer.reset
@@ -265,7 +286,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(456)).tell("log...")
* scala> writer.show
@@ -278,7 +299,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(123)).tell("hi")
* scala> writer.foldLeft(456)((acc,v) => acc + v)
@@ -293,7 +314,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* {{{
* scala> import cats.data.WriterT
* scala> import cats.Eval
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(123)).tell("hi")
* scala> writer
@@ -309,7 +330,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) {
* Example:
* {{{
* scala> import cats.data.WriterT
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(123)).tell("hi")
* scala> writer.traverse[List,Int](i => List(i))
@@ -382,9 +403,7 @@ sealed abstract private[data] class WriterTInstances1 extends WriterTInstances2
catsDataFoldableForWriterT[Id, L](F)
implicit def catsDataOrderForWriterT[F[_], L, V](implicit Ord: Order[F[(L, V)]]): Order[WriterT[F, L, V]] =
- new Order[WriterT[F, L, V]] {
- def compare(x: WriterT[F, L, V], y: WriterT[F, L, V]): Int = x.compare(y)
- }
+ _ compare _
}
sealed abstract private[data] class WriterTInstances2 extends WriterTInstances3 {
@@ -427,10 +446,7 @@ sealed abstract private[data] class WriterTInstances2 extends WriterTInstances3
fab.bimap(f, g)
}
- implicit def catsDataShowForWriterT[F[_], L, V](implicit F: Show[F[(L, V)]]): Show[WriterT[F, L, V]] =
- new Show[WriterT[F, L, V]] {
- override def show(f: WriterT[F, L, V]): String = f.show
- }
+ implicit def catsDataShowForWriterT[F[_], L, V](implicit F: Show[F[(L, V)]]): Show[WriterT[F, L, V]] = _.show
implicit def catsDataMonoidForWriterTId[L: Monoid, V: Monoid]: Monoid[WriterT[Id, L, V]] =
catsDataMonoidForWriterT[Id, L, V]
diff --git a/core/src/main/scala/cats/data/ZipList.scala b/core/src/main/scala/cats/data/ZipList.scala
index 7240ecc1a0..431efa406e 100644
--- a/core/src/main/scala/cats/data/ZipList.scala
+++ b/core/src/main/scala/cats/data/ZipList.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala/cats/data/ZipSeq.scala b/core/src/main/scala/cats/data/ZipSeq.scala
index b5e3bf1400..af6e706ae3 100644
--- a/core/src/main/scala/cats/data/ZipSeq.scala
+++ b/core/src/main/scala/cats/data/ZipSeq.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala/cats/data/ZipVector.scala b/core/src/main/scala/cats/data/ZipVector.scala
index 75f5a45736..27a88cd545 100644
--- a/core/src/main/scala/cats/data/ZipVector.scala
+++ b/core/src/main/scala/cats/data/ZipVector.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package data
diff --git a/core/src/main/scala/cats/data/package.scala b/core/src/main/scala/cats/data/package.scala
index e4b263674d..d5c87de18d 100644
--- a/core/src/main/scala/cats/data/package.scala
+++ b/core/src/main/scala/cats/data/package.scala
@@ -1,15 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package object data extends ScalaVersionSpecificPackage {
type ValidatedNel[+E, +A] = Validated[NonEmptyList[E], A]
+ type ValidatedNec[+E, +A] = Validated[NonEmptyChain[E], A]
type IorNel[+B, +A] = Ior[NonEmptyList[B], A]
type IorNec[+B, +A] = Ior[NonEmptyChain[B], A]
type IorNes[B, +A] = Ior[NonEmptySet[B], A]
type EitherNel[+E, +A] = Either[NonEmptyList[E], A]
type EitherNec[+E, +A] = Either[NonEmptyChain[E], A]
type EitherNes[E, +A] = Either[NonEmptySet[E], A]
- type ValidatedNec[+E, +A] = Validated[NonEmptyChain[E], A]
type NonEmptyMap[K, +A] = NonEmptyMapImpl.Type[K, A]
val NonEmptyMap = NonEmptyMapImpl
diff --git a/core/src/main/scala/cats/evidence/As.scala b/core/src/main/scala/cats/evidence/As.scala
index ece14025fa..4fe4800afd 100644
--- a/core/src/main/scala/cats/evidence/As.scala
+++ b/core/src/main/scala/cats/evidence/As.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package evidence
@@ -29,9 +50,9 @@ sealed abstract class As[-A, +B] extends Serializable {
*/
def substitute[F[-_]](p: F[B]): F[A]
- @inline final def andThen[C](that: (B As C)): (A As C) = As.compose(that, this)
+ @inline final def andThen[C](that: B As C): A As C = As.compose(that, this)
- @inline final def compose[C](that: (C As A)): (C As B) = As.compose(this, that)
+ @inline final def compose[C](that: C As A): C As B = As.compose(this, that)
@inline final def coerce(a: A): B = As.witness(this)(a)
@@ -52,9 +73,9 @@ sealed abstract class AsInstances {
* Subtyping forms a category
*/
implicit val liskov: Category[As] = new Category[As] {
- def id[A]: (A As A) = refl[A]
+ def id[A]: A As A = refl[A]
- def compose[A, B, C](bc: B As C, ab: A As B): (A As C) = bc.compose(ab)
+ def compose[A, B, C](bc: B As C, ab: A As B): A As C = bc.compose(ab)
}
}
@@ -71,7 +92,7 @@ object As extends AsInstances with AsSupport {
/**
* Subtyping is reflexive
*/
- implicit def refl[A]: (A As A) =
+ implicit def refl[A]: A As A =
reflAny.asInstanceOf[A As A]
/**
@@ -93,7 +114,7 @@ object As extends AsInstances with AsSupport {
/**
* reify a subtype relationship as a Liskov relationship
*/
- @inline def reify[A, B >: A]: (A As B) = refl
+ @inline def reify[A, B >: A]: A As B = refl
/**
* It can be convenient to convert a <:< value into a `<~<` value.
@@ -106,7 +127,7 @@ object As extends AsInstances with AsSupport {
/**
* We can lift subtyping into any covariant type constructor
*/
- def co[T[+_], A, A2](a: A As A2): (T[A] As T[A2]) = {
+ def co[T[+_], A, A2](a: A As A2): T[A] As T[A2] = {
type L[-α] = T[α] As T[A2]
a.substitute[L](refl)
}
@@ -158,7 +179,7 @@ object As extends AsInstances with AsSupport {
def lift2[T[+_, +_], A, A2, B, B2](
a: A As A2,
b: B As B2
- ): (T[A, B] As T[A2, B2]) = {
+ ): T[A, B] As T[A2, B2] = {
type a[-X] = T[X, B2] As T[A2, B2]
type b[-X] = T[A, X] As T[A2, B2]
b.substitute[b](a.substitute[a](refl))
@@ -171,7 +192,7 @@ object As extends AsInstances with AsSupport {
* Given that F has the shape: F[-_], we show that:
* (A As B) implies (F[B] As F[A])
*/
- def contra[T[-_], A, B](a: A As B): (T[B] As T[A]) = {
+ def contra[T[-_], A, B](a: A As B): T[B] As T[A] = {
type L[-α] = T[B] As T[α]
a.substitute[L](refl)
}
@@ -180,27 +201,27 @@ object As extends AsInstances with AsSupport {
// parameter. Here we provide the proof for what we expect to be the
// most common shapes.
- def contra1_2[T[-_, _], Z, A, B](a: A As Z): (T[Z, B] As T[A, B]) = {
+ def contra1_2[T[-_, _], Z, A, B](a: A As Z): T[Z, B] As T[A, B] = {
type L[-α] = T[Z, B] As T[α, B]
a.substitute[L](refl)
}
- def contra2_2[T[_, -_], Z, A, B](a: B As Z): (T[A, Z] As T[A, B]) = {
+ def contra2_2[T[_, -_], Z, A, B](a: B As Z): T[A, Z] As T[A, B] = {
type L[-α] = T[A, Z] As T[A, α]
a.substitute[L](refl)
}
- def contra1_3[T[-_, _, _], Z, A, B, C](a: A As Z): (T[Z, B, C] As T[A, B, C]) = {
+ def contra1_3[T[-_, _, _], Z, A, B, C](a: A As Z): T[Z, B, C] As T[A, B, C] = {
type L[-α] = T[Z, B, C] As T[α, B, C]
a.substitute[L](refl)
}
- def contra2_3[T[_, -_, _], Z, A, B, C](a: B As Z): (T[A, Z, C] As T[A, B, C]) = {
+ def contra2_3[T[_, -_, _], Z, A, B, C](a: B As Z): T[A, Z, C] As T[A, B, C] = {
type L[-α] = T[A, Z, C] As T[A, α, C]
a.substitute[L](refl)
}
- def contra3_3[T[_, _, -_], Z, A, B, C](a: C As Z): (T[A, B, Z] As T[A, B, C]) = {
+ def contra3_3[T[_, _, -_], Z, A, B, C](a: C As Z): T[A, B, Z] As T[A, B, C] = {
type L[-α] = T[A, B, Z] As T[A, B, α]
a.substitute[L](refl)
}
diff --git a/core/src/main/scala/cats/evidence/Is.scala b/core/src/main/scala/cats/evidence/Is.scala
index 4bff2ac6d2..5223e3d498 100644
--- a/core/src/main/scala/cats/evidence/Is.scala
+++ b/core/src/main/scala/cats/evidence/Is.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.evidence
import cats.Id
diff --git a/core/src/main/scala/cats/evidence/package.scala b/core/src/main/scala/cats/evidence/package.scala
index 8e127a66c6..292b7af115 100644
--- a/core/src/main/scala/cats/evidence/package.scala
+++ b/core/src/main/scala/cats/evidence/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package object evidence {
diff --git a/core/src/main/scala/cats/implicits.scala b/core/src/main/scala/cats/implicits.scala
index 5c2f3202b9..9404eda7b4 100644
--- a/core/src/main/scala/cats/implicits.scala
+++ b/core/src/main/scala/cats/implicits.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
object implicits
diff --git a/core/src/main/scala/cats/instances/StaticMethods.scala b/core/src/main/scala/cats/instances/StaticMethods.scala
new file mode 100644
index 0000000000..8df598bddd
--- /dev/null
+++ b/core/src/main/scala/cats/instances/StaticMethods.scala
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.instances
+
+import cats.Functor
+
+import scala.collection.mutable.Builder
+
+private[cats] object StaticMethods {
+
+ def appendAll[F <: Iterable[A], A](it: Iterator[F], bldr: Builder[A, F]): bldr.type = {
+ while (it.hasNext) {
+ bldr ++= it.next()
+ }
+ bldr
+ }
+
+ def mapAccumulateFromStrictFunctor[S, F[_], A, B](init: S, fa: F[A], f: (S, A) => (S, B))(implicit
+ ev: Functor[F]
+ ): (S, F[B]) = {
+ var state = init
+
+ val fb = ev.map(fa) { a =>
+ val (newState, b) = f(state, a)
+ state = newState
+ b
+ }
+
+ (state, fb)
+ }
+
+ def mapWithIndexFromStrictFunctor[F[_], A, B](fa: F[A], f: (A, Int) => B)(implicit ev: Functor[F]): F[B] = {
+ var idx = 0
+
+ ev.map(fa) { a =>
+ val b = f(a, idx)
+
+ idx += 1
+
+ b
+ }
+ }
+
+ def mapWithLongIndexFromStrictFunctor[F[_], A, B](fa: F[A], f: (A, Long) => B)(implicit ev: Functor[F]): F[B] = {
+ var idx: Long = 0L
+
+ ev.map(fa) { a =>
+ val b = f(a, idx)
+ idx += 1
+ b
+ }
+ }
+
+}
diff --git a/core/src/main/scala/cats/instances/SymbolInstances.scala b/core/src/main/scala/cats/instances/SymbolInstances.scala
index 4ec75cc115..843e1228ae 100644
--- a/core/src/main/scala/cats/instances/SymbolInstances.scala
+++ b/core/src/main/scala/cats/instances/SymbolInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.instances
import cats.Show
diff --git a/core/src/main/scala/cats/instances/anyval.scala b/core/src/main/scala/cats/instances/anyval.scala
index 8f8827738f..aea51929a0 100644
--- a/core/src/main/scala/cats/instances/anyval.scala
+++ b/core/src/main/scala/cats/instances/anyval.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala/cats/instances/bigDecimal.scala b/core/src/main/scala/cats/instances/bigDecimal.scala
index a12779cd90..c6fdb149c1 100644
--- a/core/src/main/scala/cats/instances/bigDecimal.scala
+++ b/core/src/main/scala/cats/instances/bigDecimal.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala/cats/instances/bigInt.scala b/core/src/main/scala/cats/instances/bigInt.scala
index 8aab1e01cc..ee791d8133 100644
--- a/core/src/main/scala/cats/instances/bigInt.scala
+++ b/core/src/main/scala/cats/instances/bigInt.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala/cats/instances/bitSet.scala b/core/src/main/scala/cats/instances/bitSet.scala
index dc14fe8276..1c31e6bddf 100644
--- a/core/src/main/scala/cats/instances/bitSet.scala
+++ b/core/src/main/scala/cats/instances/bitSet.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.instances
import scala.collection.immutable.BitSet
diff --git a/core/src/main/scala/cats/instances/deadline.scala b/core/src/main/scala/cats/instances/deadline.scala
index cfbc6b7e15..024d5ab603 100644
--- a/core/src/main/scala/cats/instances/deadline.scala
+++ b/core/src/main/scala/cats/instances/deadline.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala/cats/instances/duration.scala b/core/src/main/scala/cats/instances/duration.scala
index 21e2e08299..539d41fee8 100644
--- a/core/src/main/scala/cats/instances/duration.scala
+++ b/core/src/main/scala/cats/instances/duration.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala/cats/instances/either.scala b/core/src/main/scala/cats/instances/either.scala
index 8efa5ef581..efe3a912b7 100644
--- a/core/src/main/scala/cats/instances/either.scala
+++ b/core/src/main/scala/cats/instances/either.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
@@ -36,7 +57,7 @@ trait EitherInstances extends cats.kernel.instances.EitherInstances {
}
implicit def catsStdInstancesForEither[A]
- : MonadError[Either[A, *], A] with Traverse[Either[A, *]] with Align[Either[A, *]] =
+ : MonadError[Either[A, *], A] & Traverse[Either[A, *]] & Align[Either[A, *]] =
new MonadError[Either[A, *], A] with Traverse[Either[A, *]] with Align[Either[A, *]] {
override def unit: Either[A, Unit] = Either.unit
@@ -80,6 +101,15 @@ trait EitherInstances extends cats.kernel.instances.EitherInstances {
case Right(b) => F.map(f(b))(Right(_))
}
+ override def mapAccumulate[S, B, C](init: S, fa: Either[A, B])(f: (S, B) => (S, C)): (S, Either[A, C]) = {
+ fa match {
+ case Right(b) =>
+ val (snext, c) = f(init, b)
+ (snext, Right(c))
+ case l @ Left(_) => (init, l.rightCast)
+ }
+ }
+
def foldLeft[B, C](fa: Either[A, B], c: C)(f: (C, B) => C): C =
fa match {
case Left(_) => c
@@ -168,15 +198,15 @@ trait EitherInstances extends cats.kernel.instances.EitherInstances {
override def alignWith[B, C, D](fb: Either[A, B], fc: Either[A, C])(f: Ior[B, C] => D): Either[A, D] =
fb match {
- case left @ Left(a) =>
- fc match {
- case Left(_) => left.rightCast[D]
- case Right(c) => Right(f(Ior.right(c)))
- }
case Right(b) =>
fc match {
- case Left(a) => Right(f(Ior.left(b)))
case Right(c) => Right(f(Ior.both(b, c)))
+ case Left(_) => Right(f(Ior.left(b)))
+ }
+ case left @ Left(_) =>
+ fc match {
+ case Right(c) => Right(f(Ior.right(c)))
+ case Left(_) => left.rightCast[D]
}
}
@@ -201,14 +231,10 @@ trait EitherInstances extends cats.kernel.instances.EitherInstances {
}
}
- implicit def catsStdShowForEither[A, B](implicit A: Show[A], B: Show[B]): Show[Either[A, B]] =
- new Show[Either[A, B]] {
- def show(x: Either[A, B]): String =
- x match {
- case Left(a) => "Left(" + A.show(a) + ")"
- case Right(b) => "Right(" + B.show(b) + ")"
- }
- }
+ implicit def catsStdShowForEither[A, B](implicit A: Show[A], B: Show[B]): Show[Either[A, B]] = {
+ case Left(a) => "Left(" + A.show(a) + ")"
+ case Right(b) => "Right(" + B.show(b) + ")"
+ }
implicit def catsParallelForEitherAndValidated[E: Semigroup]: Parallel.Aux[Either[E, *], Validated[E, *]] =
new Parallel[Either[E, *]] {
diff --git a/core/src/main/scala/cats/instances/eq.scala b/core/src/main/scala/cats/instances/eq.scala
index 69c3429721..5c96a8c219 100644
--- a/core/src/main/scala/cats/instances/eq.scala
+++ b/core/src/main/scala/cats/instances/eq.scala
@@ -1,6 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
+import scala.annotation.tailrec
+
trait EqInstances extends kernel.instances.EqInstances {
implicit val catsContravariantMonoidalForEq: ContravariantMonoidal[Eq] =
new ContravariantMonoidal[Eq] {
@@ -20,8 +43,31 @@ trait EqInstances extends kernel.instances.EqInstances {
Eq.by(f)(fa)
def product[A, B](fa: Eq[A], fb: Eq[B]): Eq[(A, B)] =
- Eq.instance { (left, right) =>
- fa.eqv(left._1, right._1) && fb.eqv(left._2, right._2)
+ (left, right) => fa.eqv(left._1, right._1) && fb.eqv(left._2, right._2)
+ }
+
+ implicit def catsDeferForEq: Defer[Eq] = EqInstances.catsDeferForEqCache
+}
+object EqInstances {
+ private val catsDeferForEqCache: Defer[Eq] =
+ new Defer[Eq] {
+ case class Deferred[A](fa: () => Eq[A]) extends Eq[A] {
+ private lazy val resolved: Eq[A] = {
+ @tailrec
+ def loop(f: () => Eq[A]): Eq[A] =
+ f() match {
+ case Deferred(f) => loop(f)
+ case next => next
+ }
+
+ loop(fa)
}
+ override def eqv(x: A, y: A): Boolean = resolved.eqv(x, y)
+ }
+
+ override def defer[A](fa: => Eq[A]): Eq[A] = {
+ lazy val cachedFa = fa
+ Deferred(() => cachedFa)
+ }
}
}
diff --git a/core/src/main/scala/cats/instances/equiv.scala b/core/src/main/scala/cats/instances/equiv.scala
index 6730aeb1cc..941fd6e911 100644
--- a/core/src/main/scala/cats/instances/equiv.scala
+++ b/core/src/main/scala/cats/instances/equiv.scala
@@ -1,6 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
+import scala.annotation.tailrec
+
trait EquivInstances {
implicit val catsContravariantMonoidalForEquiv: ContravariantMonoidal[Equiv] =
new ContravariantMonoidal[Equiv] {
@@ -31,4 +54,29 @@ trait EquivInstances {
fa.equiv(l._1, r._1) && fb.equiv(l._2, r._2)
}
}
+
+ implicit def catsDeferForEquiv: Defer[Equiv] = EquivInstances.catsDeferForEquivCache
+}
+object EquivInstances {
+ private val catsDeferForEquivCache: Defer[Equiv] =
+ new Defer[Equiv] {
+ case class Deferred[A](fa: () => Equiv[A]) extends Equiv[A] {
+ private lazy val resolved: Equiv[A] = {
+ @tailrec
+ def loop(f: () => Equiv[A]): Equiv[A] =
+ f() match {
+ case Deferred(f) => loop(f)
+ case next => next
+ }
+
+ loop(fa)
+ }
+ override def equiv(x: A, y: A): Boolean = resolved.equiv(x, y)
+ }
+
+ override def defer[A](fa: => Equiv[A]): Equiv[A] = {
+ lazy val cachedFa = fa
+ Deferred(() => cachedFa)
+ }
+ }
}
diff --git a/core/src/main/scala/cats/instances/finiteDuration.scala b/core/src/main/scala/cats/instances/finiteDuration.scala
index f25645a8c9..9197274260 100644
--- a/core/src/main/scala/cats/instances/finiteDuration.scala
+++ b/core/src/main/scala/cats/instances/finiteDuration.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala/cats/instances/function.scala b/core/src/main/scala/cats/instances/function.scala
index 48054b57c1..af1849307e 100644
--- a/core/src/main/scala/cats/instances/function.scala
+++ b/core/src/main/scala/cats/instances/function.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
@@ -25,15 +46,17 @@ private[instances] trait FunctionInstancesBinCompat0 {
implicit val catsSddDeferForFunction0: Defer[Function0] =
new Defer[Function0] {
case class Deferred[A](fa: () => Function0[A]) extends Function0[A] {
- def apply() = {
+ private lazy val resolved: Function0[A] = {
@annotation.tailrec
- def loop(f: () => Function0[A]): A =
+ def loop(f: () => Function0[A]): Function0[A] =
f() match {
case Deferred(f) => loop(f)
- case next => next()
+ case next => next
}
+
loop(fa)
}
+ def apply(): A = resolved()
}
def defer[A](fa: => Function0[A]): Function0[A] = {
lazy val cachedFa = fa
@@ -44,15 +67,17 @@ private[instances] trait FunctionInstancesBinCompat0 {
implicit def catsStdDeferForFunction1[A]: Defer[A => *] =
new Defer[A => *] {
case class Deferred[B](fa: () => A => B) extends (A => B) {
- def apply(a: A) = {
+ private lazy val resolved: A => B = {
@annotation.tailrec
- def loop(f: () => A => B): B =
+ def loop(f: () => A => B): A => B =
f() match {
case Deferred(f) => loop(f)
- case next => next(a)
+ case next => next
}
+
loop(fa)
}
+ def apply(a: A): B = resolved(a)
}
def defer[B](fa: => A => B): A => B = {
lazy val cachedFa = fa
@@ -153,7 +178,7 @@ sealed private[instances] trait Function1Instances extends Function1Instances0 {
}
}
- implicit val catsStdInstancesForFunction1: ArrowChoice[Function1] with CommutativeArrow[Function1] =
+ implicit val catsStdInstancesForFunction1: ArrowChoice[Function1] & CommutativeArrow[Function1] =
new ArrowChoice[Function1] with CommutativeArrow[Function1] {
def choose[A, B, C, D](f: A => C)(g: B => D): Either[A, B] => Either[C, D] = {
case Left(a) => Left(f(a))
diff --git a/core/src/main/scala/cats/instances/future.scala b/core/src/main/scala/cats/instances/future.scala
index a08ad7a371..cb38dc845c 100644
--- a/core/src/main/scala/cats/instances/future.scala
+++ b/core/src/main/scala/cats/instances/future.scala
@@ -1,14 +1,44 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success}
+/**
+ * @deprecated
+ * Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
+ * (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
+ * We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
+ * However, at this time there are no plans to remove these instances from Cats.
+ *
+ * @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
+ */
trait FutureInstances extends FutureInstances1 {
implicit def catsStdInstancesForFuture(implicit
ec: ExecutionContext
- ): MonadThrow[Future] with CoflatMap[Future] with Monad[Future] =
+ ): MonadThrow[Future] & CoflatMap[Future] & Monad[Future] =
new FutureCoflatMap with MonadThrow[Future] with Monad[Future] with StackSafeMonad[Future] {
override def pure[A](x: A): Future[A] =
Future.successful(x)
diff --git a/core/src/main/scala/cats/instances/hash.scala b/core/src/main/scala/cats/instances/hash.scala
index 5b55765823..9175d0dd4f 100644
--- a/core/src/main/scala/cats/instances/hash.scala
+++ b/core/src/main/scala/cats/instances/hash.scala
@@ -1,6 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
+import scala.annotation.tailrec
+
trait HashInstances extends kernel.instances.HashInstances {
implicit val catsContravariantForHash: Contravariant[Hash] =
@@ -13,4 +36,34 @@ trait HashInstances extends kernel.instances.HashInstances {
}
+ implicit def catsDeferForHash: Defer[Hash] = HashInstances.catsDeferForHashCache
+}
+object HashInstances {
+ private val catsDeferForHashCache: Defer[Hash] =
+ new Defer[Hash] {
+ case class Deferred[A](fa: () => Hash[A]) extends Hash[A] {
+ private lazy val resolve: Hash[A] = {
+ @tailrec
+ def loop(f: () => Hash[A]): Hash[A] =
+ f() match {
+ case Deferred(f) => loop(f)
+ case next => next
+ }
+
+ loop(fa)
+ }
+
+ override def hash(x: A): Int = resolve.hash(x)
+
+ /**
+ * Returns `true` if `x` and `y` are equivalent, `false` otherwise.
+ */
+ override def eqv(x: A, y: A): Boolean = resolve.eqv(x, y)
+ }
+
+ override def defer[A](fa: => Hash[A]): Hash[A] = {
+ lazy val cachedFa = fa
+ Deferred(() => cachedFa)
+ }
+ }
}
diff --git a/core/src/main/scala/cats/instances/invariant.scala b/core/src/main/scala/cats/instances/invariant.scala
index f79f248e27..d9715c3ce1 100644
--- a/core/src/main/scala/cats/instances/invariant.scala
+++ b/core/src/main/scala/cats/instances/invariant.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.instances
import cats.kernel._
@@ -24,14 +45,10 @@ trait InvariantMonoidalInstances {
implicit val catsInvariantMonoidalSemigroup: InvariantMonoidal[Semigroup] = new InvariantMonoidal[Semigroup] {
def product[A, B](fa: Semigroup[A], fb: Semigroup[B]): Semigroup[(A, B)] =
- new Semigroup[(A, B)] {
- def combine(x: (A, B), y: (A, B)): (A, B) = fa.combine(x._1, y._1) -> fb.combine(x._2, y._2)
- }
+ (x, y) => fa.combine(x._1, y._1) -> fb.combine(x._2, y._2)
def imap[A, B](fa: Semigroup[A])(f: A => B)(g: B => A): Semigroup[B] =
- new Semigroup[B] {
- def combine(x: B, y: B): B = f(fa.combine(g(x), g(y)))
- }
+ (x, y) => f(fa.combine(g(x), g(y)))
def unit: Semigroup[Unit] = implicitly
}
@@ -39,14 +56,10 @@ trait InvariantMonoidalInstances {
implicit val catsInvariantMonoidalCommutativeSemigroup: InvariantMonoidal[CommutativeSemigroup] =
new InvariantMonoidal[CommutativeSemigroup] {
def product[A, B](fa: CommutativeSemigroup[A], fb: CommutativeSemigroup[B]): CommutativeSemigroup[(A, B)] =
- new CommutativeSemigroup[(A, B)] {
- def combine(x: (A, B), y: (A, B)): (A, B) = fa.combine(x._1, y._1) -> fb.combine(x._2, y._2)
- }
+ (x, y) => fa.combine(x._1, y._1) -> fb.combine(x._2, y._2)
def imap[A, B](fa: CommutativeSemigroup[A])(f: A => B)(g: B => A): CommutativeSemigroup[B] =
- new CommutativeSemigroup[B] {
- def combine(x: B, y: B): B = f(fa.combine(g(x), g(y)))
- }
+ (x, y) => f(fa.combine(g(x), g(y)))
def unit: CommutativeSemigroup[Unit] = implicitly
}
diff --git a/core/src/main/scala/cats/instances/list.scala b/core/src/main/scala/cats/instances/list.scala
index 0ca62ad851..53e0aab253 100644
--- a/core/src/main/scala/cats/instances/list.scala
+++ b/core/src/main/scala/cats/instances/list.scala
@@ -1,24 +1,52 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
-import cats.data.{Chain, ZipList}
+import cats.data.{Chain, Ior, ZipList}
+import cats.StackSafeMonad
+import cats.instances.StaticMethods.appendAll
+import cats.kernel.compat.scalaVersionSpecific._
import cats.kernel.instances.StaticMethods.wrapMutableIndexedSeq
-import cats.syntax.show._
import scala.annotation.tailrec
import scala.collection.mutable.ListBuffer
-import cats.data.Ior
-
trait ListInstances extends cats.kernel.instances.ListInstances {
implicit val catsStdInstancesForList
- : Traverse[List] with Alternative[List] with Monad[List] with CoflatMap[List] with Align[List] =
+ : Traverse[List] & Alternative[List] & Monad[List] & CoflatMap[List] & Align[List] =
new Traverse[List] with Alternative[List] with Monad[List] with CoflatMap[List] with Align[List] {
def empty[A]: List[A] = Nil
def combineK[A](x: List[A], y: List[A]): List[A] = x ::: y
+ override def combineAllOptionK[A](as: IterableOnce[List[A]]): Option[List[A]] = {
+ val iter = as.iterator
+ if (iter.isEmpty) None else Some(appendAll(iter, List.newBuilder[A]).result())
+ }
+
+ override def fromIterableOnce[A](as: IterableOnce[A]): List[A] = as.iterator.toList
+
override def prependK[A](a: A, fa: List[A]): List[A] = a :: fa
override def appendK[A](fa: List[A], a: A): List[A] = fa :+ a
@@ -93,50 +121,58 @@ trait ListInstances extends cats.kernel.instances.ListInstances {
def traverse[G[_], A, B](fa: List[A])(f: A => G[B])(implicit G: Applicative[G]): G[List[B]] =
if (fa.isEmpty) G.pure(Nil)
else
- G.map(Chain.traverseViaChain {
- val as = collection.mutable.ArrayBuffer[A]()
- as ++= fa
- wrapMutableIndexedSeq(as)
- }(f))(_.toList)
+ G match {
+ case x: StackSafeMonad[G] => x.map(Traverse.traverseDirectly[G, A, B](fa)(f)(x))(_.toList)
+ case _ =>
+ G.map(Chain.traverseViaChain {
+ val as = collection.mutable.ArrayBuffer[A]()
+ as ++= fa
+ wrapMutableIndexedSeq(as)
+ }(f))(_.toList)
+ }
/**
* This avoids making a very deep stack by building a tree instead
*/
- override def traverse_[G[_], A, B](fa: List[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] = {
- // the cost of this is O(size log size)
- // c(n) = n + 2 * c(n/2) = n + 2(n/2 log (n/2)) = n + n (logn - 1) = n log n
- // invariant: size >= 1
- def runHalf(size: Int, fa: List[A]): Eval[G[Unit]] =
- if (size > 1) {
- val leftSize = size / 2
- val rightSize = size - leftSize
- val (leftL, rightL) = fa.splitAt(leftSize)
- runHalf(leftSize, leftL)
- .flatMap { left =>
- val right = runHalf(rightSize, rightL)
- G.map2Eval(left, right) { (_, _) => () }
+ override def traverseVoid[G[_], A, B](fa: List[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] = {
+ G match {
+ case x: StackSafeMonad[G] => Traverse.traverseVoidDirectly(fa)(f)(x)
+ case _ =>
+ // the cost of this is O(size log size)
+ // c(n) = n + 2 * c(n/2) = n + 2(n/2 log (n/2)) = n + n (logn - 1) = n log n
+ // invariant: size >= 1
+ def runHalf(size: Int, fa: List[A]): Eval[G[Unit]] =
+ if (size > 1) {
+ val leftSize = size / 2
+ val rightSize = size - leftSize
+ val (leftL, rightL) = fa.splitAt(leftSize)
+ runHalf(leftSize, leftL)
+ .flatMap { left =>
+ val right = runHalf(rightSize, rightL)
+ G.map2Eval(left, right) { (_, _) => () }
+ }
+ } else {
+ // avoid pattern matching when we know that there is only one element
+ val a = fa.head
+ // we evaluate this at most one time,
+ // always is a bit cheaper in such cases
+ //
+ // Here is the point of the laziness using Eval:
+ // we avoid calling f(a) or G.void in the
+ // event that the computation has already
+ // failed. We do not use laziness to avoid
+ // traversing fa, which we will do fully
+ // in all cases.
+ Eval.always {
+ val gb = f(a)
+ G.void(gb)
+ }
}
- } else {
- // avoid pattern matching when we know that there is only one element
- val a = fa.head
- // we evaluate this at most one time,
- // always is a bit cheaper in such cases
- //
- // Here is the point of the laziness using Eval:
- // we avoid calling f(a) or G.void in the
- // event that the computation has already
- // failed. We do not use laziness to avoid
- // traversing fa, which we will do fully
- // in all cases.
- Eval.always {
- val gb = f(a)
- G.void(gb)
- }
- }
- val len = fa.length
- if (len == 0) G.unit
- else runHalf(len, fa).value
+ val len = fa.length
+ if (len == 0) G.unit
+ else runHalf(len, fa).value
+ }
}
def functor: Functor[List] = this
@@ -155,8 +191,14 @@ trait ListInstances extends cats.kernel.instances.ListInstances {
loop(ListBuffer.empty[C], fa, fb)
}
+ override def mapAccumulate[S, A, B](init: S, fa: List[A])(f: (S, A) => (S, B)): (S, List[B]) =
+ StaticMethods.mapAccumulateFromStrictFunctor(init, fa, f)(this)
+
+ override def mapWithLongIndex[A, B](fa: List[A])(f: (A, Long) => B): List[B] =
+ StaticMethods.mapWithLongIndexFromStrictFunctor(fa, f)(this)
+
override def mapWithIndex[A, B](fa: List[A])(f: (A, Int) => B): List[B] =
- fa.iterator.zipWithIndex.map(ai => f(ai._1, ai._2)).toList
+ StaticMethods.mapWithIndexFromStrictFunctor(fa, f)(this)
override def zipWithIndex[A](fa: List[A]): List[(A, Int)] =
fa.zipWithIndex
@@ -219,7 +261,7 @@ trait ListInstances extends cats.kernel.instances.ListInstances {
override def dropWhile_[A](fa: List[A])(p: A => Boolean): List[A] = fa.dropWhile(p)
- override def algebra[A]: Monoid[List[A]] = new kernel.instances.ListMonoid[A]
+ override def algebra[A]: Monoid[List[A]] = kernel.instances.ListMonoid[A]
override def collectFirst[A, B](fa: List[A])(pf: PartialFunction[A, B]): Option[B] = fa.collectFirst(pf)
@@ -242,10 +284,7 @@ trait ListInstances extends cats.kernel.instances.ListInstances {
}
implicit def catsStdShowForList[A: Show]: Show[List[A]] =
- new Show[List[A]] {
- def show(fa: List[A]): String =
- fa.iterator.map(_.show).mkString("List(", ", ", ")")
- }
+ _.iterator.map(Show[A].show).mkString("List(", ", ", ")")
implicit def catsStdNonEmptyParallelForListZipList: NonEmptyParallel.Aux[List, ZipList] =
new NonEmptyParallel[List] {
@@ -262,6 +301,7 @@ trait ListInstances extends cats.kernel.instances.ListInstances {
}
}
+@suppressUnusedImportWarningForScalaVersionSpecific
private[instances] trait ListInstancesBinCompat0 {
implicit val catsStdTraverseFilterForList: TraverseFilter[List] = new TraverseFilter[List] {
val traverse: Traverse[List] = cats.instances.list.catsStdInstancesForList
@@ -279,11 +319,15 @@ private[instances] trait ListInstancesBinCompat0 {
def traverseFilter[G[_], A, B](fa: List[A])(f: (A) => G[Option[B]])(implicit G: Applicative[G]): G[List[B]] =
if (fa.isEmpty) G.pure(Nil)
else
- G.map(Chain.traverseFilterViaChain {
- val as = collection.mutable.ArrayBuffer[A]()
- as ++= fa
- wrapMutableIndexedSeq(as)
- }(f))(_.toList)
+ G match {
+ case x: StackSafeMonad[G] => x.map(TraverseFilter.traverseFilterDirectly(fa)(f)(x))(_.toList)
+ case _ =>
+ G.map(Chain.traverseFilterViaChain {
+ val as = collection.mutable.ArrayBuffer[A]()
+ as ++= fa
+ wrapMutableIndexedSeq(as)
+ }(f))(_.toList)
+ }
override def filterA[G[_], A](fa: List[A])(f: (A) => G[Boolean])(implicit G: Applicative[G]): G[List[A]] =
traverse
diff --git a/core/src/main/scala/cats/instances/map.scala b/core/src/main/scala/cats/instances/map.scala
index 02960cf0a1..dfcc960bac 100644
--- a/core/src/main/scala/cats/instances/map.scala
+++ b/core/src/main/scala/cats/instances/map.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
@@ -6,33 +27,33 @@ import cats.kernel.CommutativeMonoid
import scala.annotation.tailrec
import cats.arrow.Compose
-import cats.data.Ior
+import cats.data.{Chain, Ior}
trait MapInstances extends cats.kernel.instances.MapInstances {
implicit def catsStdShowForMap[A, B](implicit showA: Show[A], showB: Show[B]): Show[Map[A, B]] =
- new Show[Map[A, B]] {
- def show(m: Map[A, B]): String =
- m.iterator
- .map { case (a, b) => showA.show(a) + " -> " + showB.show(b) }
- .mkString("Map(", ", ", ")")
- }
+ _.iterator
+ .map { case (a, b) => showA.show(a) + " -> " + showB.show(b) }
+ .mkString("Map(", ", ", ")")
- implicit def catsStdInstancesForMap[K]: UnorderedTraverse[Map[K, *]] with FlatMap[Map[K, *]] with Align[Map[K, *]] =
+ implicit def catsStdInstancesForMap[K]: UnorderedTraverse[Map[K, *]] & FlatMap[Map[K, *]] & Align[Map[K, *]] =
new UnorderedTraverse[Map[K, *]] with FlatMap[Map[K, *]] with Align[Map[K, *]] {
def unorderedTraverse[G[_], A, B](
fa: Map[K, A]
)(f: A => G[B])(implicit G: CommutativeApplicative[G]): G[Map[K, B]] = {
- val gba: Eval[G[Map[K, B]]] = Always(G.pure(Map.empty))
- val gbb = Foldable
- .iterateRight(fa, gba) { (kv, lbuf) =>
- G.map2Eval(f(kv._2), lbuf) { (b, buf) =>
- buf + (kv._1 -> b)
- }
+ if (fa.isEmpty) G.pure(Map.empty[K, B])
+ else
+ G match {
+ case x: StackSafeMonad[G] =>
+ fa.iterator.foldLeft(G.pure(Map.empty[K, B])) { case (accG, (k, a)) =>
+ x.map2(accG, f(a)) { case (acc, b) => acc + (k -> b) }
+ }
+ case _ =>
+ G.map(Chain.traverseViaChain(fa.toIndexedSeq) { case (k, a) =>
+ G.map(f(a))((k, _))
+ })(_.iterator.toMap)
}
- .value
- G.map(gbb)(_.toMap)
}
override def map[A, B](fa: Map[K, A])(f: A => B): Map[K, B] =
@@ -57,8 +78,8 @@ trait MapInstances extends cats.kernel.instances.MapInstances {
def flatMap[A, B](fa: Map[K, A])(f: (A) => Map[K, B]): Map[K, B] =
fa.flatMap { case (k, a) => f(a).get(k).map((k, _)) }
- def unorderedFoldMap[A, B: CommutativeMonoid](fa: Map[K, A])(f: (A) => B) =
- fa.foldLeft(Monoid[B].empty) { case (b, (k, a)) => Monoid[B].combine(b, f(a)) }
+ def unorderedFoldMap[A, B: CommutativeMonoid](fa: Map[K, A])(f: A => B): B =
+ Monoid[B].combineAll(fa.valuesIterator.map(f))
def tailRecM[A, B](a: A)(f: A => Map[K, Either[A, B]]): Map[K, B] = {
val bldr = Map.newBuilder[K, B]
@@ -120,7 +141,7 @@ private[instances] trait MapInstancesBinCompat0 {
* Compose two maps `g` and `f` by using the values in `f` as keys for `g`.
* {{{
* scala> import cats.arrow.Compose
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val first = Map(1 -> "a", 2 -> "b", 3 -> "c", 4 -> "a")
* scala> val second = Map("a" -> true, "b" -> false, "d" -> true)
* scala> Compose[Map].compose(second, first)
diff --git a/core/src/main/scala/cats/instances/option.scala b/core/src/main/scala/cats/instances/option.scala
index 04fd8a4ded..43abeec786 100644
--- a/core/src/main/scala/cats/instances/option.scala
+++ b/core/src/main/scala/cats/instances/option.scala
@@ -1,17 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import scala.annotation.tailrec
import cats.data.Ior
+import cats.kernel.compat.scalaVersionSpecific._
trait OptionInstances extends cats.kernel.instances.OptionInstances {
- implicit val catsStdInstancesForOption: Traverse[Option]
- with MonadError[Option, Unit]
- with Alternative[Option]
- with CommutativeMonad[Option]
- with CoflatMap[Option]
- with Align[Option] =
+ implicit val catsStdInstancesForOption: Traverse[Option] & MonadError[Option, Unit] & Alternative[
+ Option
+ ] & CommutativeMonad[Option] & CoflatMap[Option] & Align[Option] =
new Traverse[Option]
with MonadError[Option, Unit]
with Alternative[Option]
@@ -25,6 +44,25 @@ trait OptionInstances extends cats.kernel.instances.OptionInstances {
def combineK[A](x: Option[A], y: Option[A]): Option[A] = if (x.isDefined) x else y
+ override def combineAllOptionK[A](as: IterableOnce[Option[A]]): Option[Option[A]] = {
+ val it = as.iterator
+ if (it.hasNext) {
+ while (true) {
+ val o = it.next()
+ if (o.isDefined) return Some(o)
+ if (!it.hasNext) return Some(None)
+ }
+ sys.error("unreachable")
+ } else {
+ return None
+ }
+ }
+
+ override def fromIterableOnce[A](as: IterableOnce[A]): Option[A] = {
+ val iter = as.iterator
+ if (iter.hasNext) Some(iter.next()) else None
+ }
+
override def prependK[A](a: A, fa: Option[A]): Option[A] = Some(a)
override def appendK[A](fa: Option[A], a: A): Option[A] = if (fa.isDefined) fa else Some(a)
@@ -134,6 +172,15 @@ trait OptionInstances extends cats.kernel.instances.OptionInstances {
case Some(a) => Applicative[G].map(f(a))(Some(_))
}
+ override def mapAccumulate[S, A, B](init: S, fa: Option[A])(f: (S, A) => (S, B)): (S, Option[B]) = {
+ fa match {
+ case Some(a) =>
+ val (snext, b) = f(init, a)
+ (snext, Some(b))
+ case None => (init, None)
+ }
+ }
+
override def reduceLeftToOption[A, B](fa: Option[A])(f: A => B)(g: (B, A) => B): Option[B] =
fa.map(f)
@@ -202,16 +249,13 @@ trait OptionInstances extends cats.kernel.instances.OptionInstances {
if (oa.isDefined) someUnit else None
}
- implicit def catsStdShowForOption[A](implicit A: Show[A]): Show[Option[A]] =
- new Show[Option[A]] {
- def show(fa: Option[A]): String =
- fa match {
- case Some(a) => s"Some(${A.show(a)})"
- case None => "None"
- }
- }
+ implicit def catsStdShowForOption[A](implicit A: Show[A]): Show[Option[A]] = {
+ case Some(a) => s"Some(${A.show(a)})"
+ case None => "None"
+ }
}
+@suppressUnusedImportWarningForScalaVersionSpecific
private[instances] trait OptionInstancesBinCompat0 {
implicit val catsStdTraverseFilterForOption: TraverseFilter[Option] = new TraverseFilter[Option] {
val traverse: Traverse[Option] = cats.instances.option.catsStdInstancesForOption
diff --git a/core/src/main/scala/cats/instances/order.scala b/core/src/main/scala/cats/instances/order.scala
index 96b26eefba..c1b4eab29b 100644
--- a/core/src/main/scala/cats/instances/order.scala
+++ b/core/src/main/scala/cats/instances/order.scala
@@ -1,8 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import cats.kernel.instances.unit._
+import scala.annotation.tailrec
+
trait OrderInstances extends kernel.instances.OrderInstances {
implicit val catsContravariantMonoidalForOrder: ContravariantMonoidal[Order] =
@@ -21,12 +44,34 @@ trait OrderInstances extends kernel.instances.OrderInstances {
def contramap[A, B](fa: Order[A])(f: B => A): Order[B] =
Order.by(f)(fa)
- def product[A, B](fa: Order[A], fb: Order[B]): Order[(A, B)] =
- new Order[(A, B)] {
- def compare(x: (A, B), y: (A, B)): Int = {
- val z = fa.compare(x._1, y._1)
- if (z == 0) fb.compare(x._2, y._2) else z
- }
+ def product[A, B](fa: Order[A], fb: Order[B]): Order[(A, B)] = { (x, y) =>
+ val z = fa.compare(x._1, y._1)
+ if (z == 0) fb.compare(x._2, y._2) else z
+ }
+ }
+
+ implicit def catsDeferForOrder: Defer[Order] = OrderInstances.catsDeferForOrderCache
+}
+object OrderInstances {
+ private val catsDeferForOrderCache: Defer[Order] =
+ new Defer[Order] {
+ case class Deferred[A](fa: () => Order[A]) extends Order[A] {
+ private lazy val resolved: Order[A] = {
+ @tailrec
+ def loop(f: () => Order[A]): Order[A] =
+ f() match {
+ case Deferred(f) => loop(f)
+ case next => next
+ }
+
+ loop(fa)
}
+ override def compare(x: A, y: A): Int = resolved.compare(x, y)
+ }
+
+ override def defer[A](fa: => Order[A]): Order[A] = {
+ lazy val cachedFa = fa
+ Deferred(() => cachedFa)
+ }
}
}
diff --git a/core/src/main/scala/cats/instances/ordering.scala b/core/src/main/scala/cats/instances/ordering.scala
index 23cbd7e071..802e778e20 100644
--- a/core/src/main/scala/cats/instances/ordering.scala
+++ b/core/src/main/scala/cats/instances/ordering.scala
@@ -1,8 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import cats.kernel.instances.unit._
+import scala.annotation.tailrec
+
trait OrderingInstances {
implicit val catsContravariantMonoidalForOrdering: ContravariantMonoidal[Ordering] =
new ContravariantMonoidal[Ordering] {
@@ -22,4 +45,29 @@ trait OrderingInstances {
}
}
}
+
+ implicit def catsStdDeferForOrdering: Defer[Ordering] = OrderingInstances.catsStdDeferForOrderingCache
+}
+object OrderingInstances {
+ private val catsStdDeferForOrderingCache: Defer[Ordering] =
+ new Defer[Ordering] {
+ case class Deferred[A](fa: () => Ordering[A]) extends Ordering[A] {
+ private lazy val resolved: Ordering[A] = {
+ @tailrec
+ def loop(f: () => Ordering[A]): Ordering[A] =
+ f() match {
+ case Deferred(f) => loop(f)
+ case next => next
+ }
+
+ loop(fa)
+ }
+ override def compare(x: A, y: A): Int = resolved.compare(x, y)
+ }
+
+ override def defer[A](fa: => Ordering[A]): Ordering[A] = {
+ lazy val cachedFa = fa
+ Deferred(() => cachedFa)
+ }
+ }
}
diff --git a/core/src/main/scala/cats/instances/parallel.scala b/core/src/main/scala/cats/instances/parallel.scala
index 9b27a747e3..7949854e3c 100644
--- a/core/src/main/scala/cats/instances/parallel.scala
+++ b/core/src/main/scala/cats/instances/parallel.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala/cats/instances/partialFunction.scala b/core/src/main/scala/cats/instances/partialFunction.scala
index 98a0bec94c..2c0f9f0354 100644
--- a/core/src/main/scala/cats/instances/partialFunction.scala
+++ b/core/src/main/scala/cats/instances/partialFunction.scala
@@ -1,15 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.instances
import cats.arrow.{ArrowChoice, CommutativeArrow}
trait PartialFunctionInstances {
- implicit def catsStdInstancesForPartialFunction: ArrowChoice[PartialFunction] with CommutativeArrow[PartialFunction] =
+ implicit def catsStdInstancesForPartialFunction: ArrowChoice[PartialFunction] & CommutativeArrow[PartialFunction] =
PartialFunctionInstances.instance
}
private object PartialFunctionInstances {
- private val instance: ArrowChoice[PartialFunction] with CommutativeArrow[PartialFunction] =
+ private val instance: ArrowChoice[PartialFunction] & CommutativeArrow[PartialFunction] =
new ArrowChoice[PartialFunction] with CommutativeArrow[PartialFunction] {
/**
diff --git a/core/src/main/scala/cats/instances/partialOrder.scala b/core/src/main/scala/cats/instances/partialOrder.scala
index e9121dd182..81bdce03e1 100644
--- a/core/src/main/scala/cats/instances/partialOrder.scala
+++ b/core/src/main/scala/cats/instances/partialOrder.scala
@@ -1,7 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import cats.kernel.instances.unit._
+import scala.annotation.tailrec
+
trait PartialOrderInstances extends kernel.instances.PartialOrderInstances {
implicit val catsContravariantMonoidalForPartialOrder: ContravariantMonoidal[PartialOrder] =
new ContravariantMonoidal[PartialOrder] {
@@ -13,14 +36,36 @@ trait PartialOrderInstances extends kernel.instances.PartialOrderInstances {
*/
def contramap[A, B](fa: PartialOrder[A])(f: B => A): PartialOrder[B] = PartialOrder.by[B, A](f)(fa)
- def product[A, B](fa: PartialOrder[A], fb: PartialOrder[B]): PartialOrder[(A, B)] =
- new PartialOrder[(A, B)] {
- def partialCompare(x: (A, B), y: (A, B)): Double = {
- val z = fa.partialCompare(x._1, y._1)
- if (z == 0.0) fb.partialCompare(x._2, y._2) else z
- }
- }
+ def product[A, B](fa: PartialOrder[A], fb: PartialOrder[B]): PartialOrder[(A, B)] = { (x, y) =>
+ val z = fa.partialCompare(x._1, y._1)
+ if (z == 0.0) fb.partialCompare(x._2, y._2) else z
+ }
def unit: PartialOrder[Unit] = Order[Unit]
}
+
+ implicit def catsDeferForPartialOrder: Defer[PartialOrder] = PartialOrderInstances.catsDeferForPartialOrderCache
+}
+object PartialOrderInstances {
+ private val catsDeferForPartialOrderCache: Defer[PartialOrder] =
+ new Defer[PartialOrder] {
+ case class Deferred[A](fa: () => PartialOrder[A]) extends PartialOrder[A] {
+ private lazy val resolved: PartialOrder[A] = {
+ @tailrec
+ def loop(f: () => PartialOrder[A]): PartialOrder[A] =
+ f() match {
+ case Deferred(f) => loop(f)
+ case next => next
+ }
+
+ loop(fa)
+ }
+ override def partialCompare(x: A, y: A): Double = resolved.partialCompare(x, y)
+ }
+
+ override def defer[A](fa: => PartialOrder[A]): PartialOrder[A] = {
+ lazy val cachedFa = fa
+ Deferred(() => cachedFa)
+ }
+ }
}
diff --git a/core/src/main/scala/cats/instances/partialOrdering.scala b/core/src/main/scala/cats/instances/partialOrdering.scala
index ce57853f32..586c9492dd 100644
--- a/core/src/main/scala/cats/instances/partialOrdering.scala
+++ b/core/src/main/scala/cats/instances/partialOrdering.scala
@@ -1,6 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
+import scala.annotation.tailrec
+
trait PartialOrderingInstances {
implicit val catsContravariantMonoidalForPartialOrdering: ContravariantMonoidal[PartialOrdering] =
new ContravariantMonoidal[PartialOrdering] {
@@ -29,4 +52,33 @@ trait PartialOrderingInstances {
def unit: PartialOrdering[Unit] = cats.instances.unit.catsKernelStdOrderForUnit.toOrdering
}
+
+ implicit def catsStdDeferForPartialOrdering: Defer[PartialOrdering] =
+ PartialOrderingInstances.catsStdDeferForPartialOrderingCache
+}
+object PartialOrderingInstances {
+ private val catsStdDeferForPartialOrderingCache: Defer[PartialOrdering] =
+ new Defer[PartialOrdering] {
+ case class Deferred[A](fa: () => PartialOrdering[A]) extends PartialOrdering[A] {
+ private lazy val resolve: PartialOrdering[A] = {
+ @tailrec
+ def loop(f: () => PartialOrdering[A]): PartialOrdering[A] =
+ f() match {
+ case Deferred(f) => loop(f)
+ case next => next
+ }
+
+ loop(fa)
+ }
+
+ override def tryCompare(x: A, y: A): Option[Int] = resolve.tryCompare(x, y)
+
+ override def lteq(x: A, y: A): Boolean = resolve.lteq(x, y)
+ }
+
+ override def defer[A](fa: => PartialOrdering[A]): PartialOrdering[A] = {
+ lazy val cachedFa = fa
+ Deferred(() => cachedFa)
+ }
+ }
}
diff --git a/core/src/main/scala/cats/instances/queue.scala b/core/src/main/scala/cats/instances/queue.scala
index 07de24626a..f7678ff3e8 100644
--- a/core/src/main/scala/cats/instances/queue.scala
+++ b/core/src/main/scala/cats/instances/queue.scala
@@ -1,22 +1,55 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import cats.data.Chain
+import cats.instances.StaticMethods.appendAll
+import cats.kernel.compat.scalaVersionSpecific._
import cats.kernel.instances.StaticMethods.wrapMutableIndexedSeq
-import cats.syntax.show._
+
import scala.annotation.tailrec
import scala.collection.immutable.Queue
import scala.util.Try
trait QueueInstances extends cats.kernel.instances.QueueInstances {
- implicit val catsStdInstancesForQueue
- : Traverse[Queue] with Alternative[Queue] with Monad[Queue] with CoflatMap[Queue] =
+ implicit val catsStdInstancesForQueue: Traverse[Queue] & Alternative[Queue] & Monad[Queue] & CoflatMap[Queue] =
new Traverse[Queue] with Alternative[Queue] with Monad[Queue] with CoflatMap[Queue] {
def empty[A]: Queue[A] = Queue.empty
def combineK[A](x: Queue[A], y: Queue[A]): Queue[A] = x ++ y
+ override def combineAllOptionK[A](as: IterableOnce[Queue[A]]): Option[Queue[A]] = {
+ val iter = as.iterator
+ if (iter.isEmpty) None else Some(appendAll(iter, Queue.newBuilder[A]).result())
+ }
+
+ override def fromIterableOnce[A](as: IterableOnce[A]): Queue[A] = {
+ val builder = Queue.newBuilder[A]
+ builder ++= as
+ builder.result()
+ }
+
override def prependK[A](a: A, fa: Queue[A]): Queue[A] = a +: fa
override def appendK[A](fa: Queue[A], a: A): Queue[A] = fa.enqueue(a)
@@ -87,19 +120,38 @@ trait QueueInstances extends cats.kernel.instances.QueueInstances {
def traverse[G[_], A, B](fa: Queue[A])(f: A => G[B])(implicit G: Applicative[G]): G[Queue[B]] =
if (fa.isEmpty) G.pure(Queue.empty[B])
else
- G.map(Chain.traverseViaChain {
- val as = collection.mutable.ArrayBuffer[A]()
- as ++= fa
- wrapMutableIndexedSeq(as)
- }(f)) { chain =>
- chain.foldLeft(Queue.empty[B])(_ :+ _)
+ G match {
+ case x: StackSafeMonad[G] =>
+ G.map(Traverse.traverseDirectly(fa)(f)(x))(c => fromIterableOnce(c.iterator))
+ case _ =>
+ G.map(Chain.traverseViaChain {
+ val as = collection.mutable.ArrayBuffer[A]()
+ as ++= fa
+ wrapMutableIndexedSeq(as)
+ }(f)) { chain =>
+ chain.foldLeft(Queue.empty[B])(_ :+ _)
+ }
}
- override def mapWithIndex[A, B](fa: Queue[A])(f: (A, Int) => B): Queue[B] = {
- val b = Queue.newBuilder[B]
- fa.iterator.zipWithIndex.map(ai => f(ai._1, ai._2)).foreach(b += _)
- b.result()
- }
+ override def traverseVoid[G[_], A, B](fa: Queue[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] =
+ G match {
+ case x: StackSafeMonad[G] => Traverse.traverseVoidDirectly(fa)(f)(x)
+ case _ =>
+ foldRight(fa, Eval.now(G.unit)) { (a, acc) =>
+ G.map2Eval(f(a), acc) { (_, _) =>
+ ()
+ }
+ }.value
+ }
+
+ override def mapAccumulate[S, A, B](init: S, fa: Queue[A])(f: (S, A) => (S, B)): (S, Queue[B]) =
+ StaticMethods.mapAccumulateFromStrictFunctor(init, fa, f)(this)
+
+ override def mapWithLongIndex[A, B](fa: Queue[A])(f: (A, Long) => B): Queue[B] =
+ StaticMethods.mapWithLongIndexFromStrictFunctor(fa, f)(this)
+
+ override def mapWithIndex[A, B](fa: Queue[A])(f: (A, Int) => B): Queue[B] =
+ StaticMethods.mapWithIndexFromStrictFunctor(fa, f)(this)
override def zipWithIndex[A](fa: Queue[A]): Queue[(A, Int)] =
fa.zipWithIndex
@@ -153,7 +205,7 @@ trait QueueInstances extends cats.kernel.instances.QueueInstances {
fa.iterator.dropWhile(p).toList
override def algebra[A]: Monoid[Queue[A]] =
- new kernel.instances.QueueMonoid[A]
+ kernel.instances.QueueMonoid[A]
override def collectFirst[A, B](fa: Queue[A])(pf: PartialFunction[A, B]): Option[B] = fa.collectFirst(pf)
@@ -162,17 +214,15 @@ trait QueueInstances extends cats.kernel.instances.QueueInstances {
}
implicit def catsStdShowForQueue[A: Show]: Show[Queue[A]] =
- new Show[Queue[A]] {
- def show(fa: Queue[A]): String =
- fa.iterator.map(_.show).mkString("Queue(", ", ", ")")
- }
+ _.iterator.map(Show[A].show).mkString("Queue(", ", ", ")")
implicit def catsStdTraverseFilterForQueue: TraverseFilter[Queue] = QueueInstances.catsStdTraverseFilterForQueue
}
+@suppressUnusedImportWarningForScalaVersionSpecific
private object QueueInstances {
private val catsStdTraverseFilterForQueue: TraverseFilter[Queue] = new TraverseFilter[Queue] {
- val traverse: Traverse[Queue] = cats.instances.queue.catsStdInstancesForQueue
+ val traverse: Traverse[Queue] & Alternative[Queue] = cats.instances.queue.catsStdInstancesForQueue
override def mapFilter[A, B](fa: Queue[A])(f: (A) => Option[B]): Queue[B] =
fa.collect(Function.unlift(f))
@@ -188,12 +238,17 @@ private object QueueInstances {
def traverseFilter[G[_], A, B](fa: Queue[A])(f: (A) => G[Option[B]])(implicit G: Applicative[G]): G[Queue[B]] =
if (fa.isEmpty) G.pure(Queue.empty[B])
else
- G.map(Chain.traverseFilterViaChain {
- val as = collection.mutable.ArrayBuffer[A]()
- as ++= fa
- wrapMutableIndexedSeq(as)
- }(f)) { chain =>
- chain.foldLeft(Queue.empty[B])(_ :+ _)
+ G match {
+ case x: StackSafeMonad[G] =>
+ x.map(TraverseFilter.traverseFilterDirectly(fa)(f)(x))(c => traverse.fromIterableOnce(c.iterator))
+ case _ =>
+ G.map(Chain.traverseFilterViaChain {
+ val as = collection.mutable.ArrayBuffer[A]()
+ as ++= fa
+ wrapMutableIndexedSeq(as)
+ }(f)) { chain =>
+ chain.foldLeft(Queue.empty[B])(_ :+ _)
+ }
}
override def filterA[G[_], A](fa: Queue[A])(f: (A) => G[Boolean])(implicit G: Applicative[G]): G[Queue[A]] =
diff --git a/core/src/main/scala/cats/instances/seq.scala b/core/src/main/scala/cats/instances/seq.scala
index 88bcd9e010..4dc7557c41 100644
--- a/core/src/main/scala/cats/instances/seq.scala
+++ b/core/src/main/scala/cats/instances/seq.scala
@@ -1,22 +1,55 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
-import cats.data.{Chain, ZipSeq}
+import cats.data.{Chain, Ior, ZipSeq}
+import cats.instances.StaticMethods.appendAll
+import cats.kernel.compat.scalaVersionSpecific._
import scala.annotation.tailrec
-import scala.collection.{+:, mutable}
+import scala.collection.mutable
import scala.collection.immutable.Seq
-import cats.data.Ior
+@suppressUnusedImportWarningForScalaVersionSpecific
trait SeqInstances extends cats.kernel.instances.SeqInstances {
- implicit val catsStdInstancesForSeq
- : Traverse[Seq] with Monad[Seq] with Alternative[Seq] with CoflatMap[Seq] with Align[Seq] =
+ implicit val catsStdInstancesForSeq: Traverse[Seq] & Monad[Seq] & Alternative[Seq] & CoflatMap[Seq] & Align[Seq] =
new Traverse[Seq] with Monad[Seq] with Alternative[Seq] with CoflatMap[Seq] with Align[Seq] {
def empty[A]: Seq[A] = Seq.empty[A]
def combineK[A](x: Seq[A], y: Seq[A]): Seq[A] = x ++ y
+ override def combineAllOptionK[A](as: IterableOnce[Seq[A]]): Option[Seq[A]] = {
+ val iter = as.iterator
+ if (iter.isEmpty) None else Some(appendAll(iter, Seq.newBuilder[A]).result())
+ }
+
+ override def fromIterableOnce[A](as: IterableOnce[A]): Seq[A] = {
+ val builder = Seq.newBuilder[A]
+ builder ++= as
+ builder.result()
+ }
+
override def prependK[A](a: A, fa: Seq[A]): Seq[A] = a +: fa
override def appendK[A](fa: Seq[A], a: A): Seq[A] = fa :+ a
@@ -51,11 +84,8 @@ trait SeqInstances extends cats.kernel.instances.SeqInstances {
def foldLeft[A, B](fa: Seq[A], b: B)(f: (B, A) => B): B =
fa.foldLeft(b)(f)
- def foldRight[A, B](fa: Seq[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = {
- def loop(i: Int): Eval[B] =
- if (i < fa.length) f(fa(i), Eval.defer(loop(i + 1))) else lb
- Eval.defer(loop(0))
- }
+ def foldRight[A, B](fa: Seq[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
+ Foldable.iterateRight(fa, lb)(f)
override def foldMap[A, B](fa: Seq[A])(f: A => B)(implicit B: Monoid[B]): B =
B.combineAll(fa.iterator.map(f))
@@ -96,10 +126,26 @@ trait SeqInstances extends cats.kernel.instances.SeqInstances {
}
final override def traverse[G[_], A, B](fa: Seq[A])(f: A => G[B])(implicit G: Applicative[G]): G[Seq[B]] =
- G.map(Chain.traverseViaChain(fa.toIndexedSeq)(f))(_.toVector)
+ G match {
+ case x: StackSafeMonad[G] =>
+ x.map(Traverse.traverseDirectly(fa)(f)(x))(_.toList)
+ case _ =>
+ G.map(Chain.traverseViaChain(fa.toIndexedSeq)(f))(_.toList)
+ }
+
+ override def traverseVoid[G[_], A, B](fa: Seq[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] =
+ G match {
+ case x: StackSafeMonad[G] => Traverse.traverseVoidDirectly(fa)(f)(x)
+ case _ =>
+ foldRight(fa, Eval.now(G.unit)) { (a, acc) =>
+ G.map2Eval(f(a), acc) { (_, _) =>
+ ()
+ }
+ }.value
+ }
override def mapWithIndex[A, B](fa: Seq[A])(f: (A, Int) => B): Seq[B] =
- fa.iterator.zipWithIndex.map(ai => f(ai._1, ai._2)).toIndexedSeq
+ fa.zipWithIndex.map(ai => f(ai._1, ai._2))
override def zipWithIndex[A](fa: Seq[A]): Seq[(A, Int)] =
fa.zipWithIndex
@@ -128,7 +174,7 @@ trait SeqInstances extends cats.kernel.instances.SeqInstances {
override def find[A](fa: Seq[A])(f: A => Boolean): Option[A] = fa.find(f)
- override def algebra[A]: Monoid[Seq[A]] = new kernel.instances.SeqMonoid[A]
+ override def algebra[A]: Monoid[Seq[A]] = kernel.instances.SeqMonoid[A]
def functor: Functor[Seq] = this
@@ -162,7 +208,11 @@ trait SeqInstances extends cats.kernel.instances.SeqInstances {
override def flattenOption[A](fa: Seq[Option[A]]): Seq[A] = fa.flatten
def traverseFilter[G[_], A, B](fa: Seq[A])(f: (A) => G[Option[B]])(implicit G: Applicative[G]): G[Seq[B]] =
- G.map(Chain.traverseFilterViaChain(fa.toIndexedSeq)(f))(_.toVector)
+ G match {
+ case x: StackSafeMonad[G] => x.map(TraverseFilter.traverseFilterDirectly(fa)(f)(x))(_.toVector)
+ case _ =>
+ G.map(Chain.traverseFilterViaChain(fa.toIndexedSeq)(f))(_.toVector)
+ }
override def filterA[G[_], A](fa: Seq[A])(f: (A) => G[Boolean])(implicit G: Applicative[G]): G[Seq[A]] =
traverse
@@ -173,10 +223,7 @@ trait SeqInstances extends cats.kernel.instances.SeqInstances {
}
implicit def catsStdShowForSeq[A: Show]: Show[Seq[A]] =
- new Show[Seq[A]] {
- def show(fa: Seq[A]): String =
- fa.toString()
- }
+ _.map(Show[A].show).toString
implicit def catsStdNonEmptyParallelForSeqZipSeq: NonEmptyParallel.Aux[Seq, ZipSeq] =
new NonEmptyParallel[Seq] {
diff --git a/core/src/main/scala/cats/instances/set.scala b/core/src/main/scala/cats/instances/set.scala
index a63d0fe64b..5597630bfa 100644
--- a/core/src/main/scala/cats/instances/set.scala
+++ b/core/src/main/scala/cats/instances/set.scala
@@ -1,13 +1,32 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import cats.kernel.CommutativeMonoid
-import cats.syntax.show._
-
trait SetInstances extends cats.kernel.instances.SetInstances {
- implicit val catsStdInstancesForSet: UnorderedTraverse[Set] with MonoidK[Set] =
+ implicit val catsStdInstancesForSet: UnorderedTraverse[Set] & MonoidK[Set] =
new UnorderedTraverse[Set] with MonoidK[Set] {
def unorderedTraverse[G[_]: CommutativeApplicative, A, B](sa: Set[A])(f: A => G[B]): G[Set[B]] =
@@ -40,8 +59,5 @@ trait SetInstances extends cats.kernel.instances.SetInstances {
}
implicit def catsStdShowForSet[A: Show]: Show[Set[A]] =
- new Show[Set[A]] {
- def show(fa: Set[A]): String =
- fa.iterator.map(_.show).mkString("Set(", ", ", ")")
- }
+ _.iterator.map(Show[A].show).mkString("Set(", ", ", ")")
}
diff --git a/core/src/main/scala/cats/instances/show.scala b/core/src/main/scala/cats/instances/show.scala
new file mode 100644
index 0000000000..2f2c01907a
--- /dev/null
+++ b/core/src/main/scala/cats/instances/show.scala
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats
+package instances
+
+import scala.annotation.tailrec
+
+trait ShowInstances {
+ implicit def catsDeferForShow: Defer[Show] = ShowInstances.catsDeferForShowCache
+}
+object ShowInstances {
+ private val catsDeferForShowCache: Defer[Show] =
+ new Defer[Show] {
+ case class Deferred[A](fa: () => Show[A]) extends Show[A] {
+ private lazy val resolved: Show[A] = {
+ @tailrec
+ def loop(f: () => Show[A]): Show[A] =
+ f() match {
+ case Deferred(f) => loop(f)
+ case next => next
+ }
+
+ loop(fa)
+ }
+ override def show(t: A): String = resolved.show(t)
+ }
+
+ override def defer[A](fa: => Show[A]): Show[A] = {
+ lazy val cachedFa = fa
+ Deferred(() => cachedFa)
+ }
+ }
+}
diff --git a/core/src/main/scala/cats/instances/sortedMap.scala b/core/src/main/scala/cats/instances/sortedMap.scala
index 81caffbbda..e219b03458 100644
--- a/core/src/main/scala/cats/instances/sortedMap.scala
+++ b/core/src/main/scala/cats/instances/sortedMap.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.instances
import cats._
@@ -28,7 +49,7 @@ trait SortedMapInstances extends SortedMapInstances2 {
catsStdShowForSortedMap(showA, showB)
implicit def catsStdInstancesForSortedMap[K]
- : Traverse[SortedMap[K, *]] with FlatMap[SortedMap[K, *]] with Align[SortedMap[K, *]] =
+ : Traverse[SortedMap[K, *]] & FlatMap[SortedMap[K, *]] & Align[SortedMap[K, *]] =
new Traverse[SortedMap[K, *]] with FlatMap[SortedMap[K, *]] with Align[SortedMap[K, *]] {
def traverse[G[_], A, B](fa: SortedMap[K, A])(f: A => G[B])(implicit G: Applicative[G]): G[SortedMap[K, B]] = {
@@ -44,6 +65,9 @@ trait SortedMapInstances extends SortedMapInstances2 {
}) { chain => chain.foldLeft(SortedMap.empty[K, B]) { case (m, (k, b)) => m.updated(k, b) } }
}
+ override def mapAccumulate[S, A, B](init: S, fa: SortedMap[K, A])(f: (S, A) => (S, B)): (S, SortedMap[K, B]) =
+ StaticMethods.mapAccumulateFromStrictFunctor(init, fa, f)(this)
+
def flatMap[A, B](fa: SortedMap[K, A])(f: A => SortedMap[K, B]): SortedMap[K, B] = {
implicit val ordering: Ordering[K] = fa.ordering
fa.flatMap { case (k, a) => f(a).get(k).map((k, _)) }
@@ -79,7 +103,7 @@ trait SortedMapInstances extends SortedMapInstances2 {
def tailRecM[A, B](a: A)(f: A => SortedMap[K, Either[A, B]]): SortedMap[K, B] = {
val fa = f(a)
- var bldr = SortedMap.newBuilder[K, B](fa.ordering)
+ val bldr = SortedMap.newBuilder[K, B](fa.ordering)
@tailrec def descend(k: K, either: Either[A, B]): Unit =
either match {
@@ -150,7 +174,7 @@ trait SortedMapInstances extends SortedMapInstances2 {
@deprecated("Use catsStdInstancesForSortedMap override without Order", "2.2.0-M3")
def catsStdInstancesForSortedMap[K](
orderK: Order[K]
- ): Traverse[SortedMap[K, *]] with FlatMap[SortedMap[K, *]] with Align[SortedMap[K, *]] =
+ ): Traverse[SortedMap[K, *]] & FlatMap[SortedMap[K, *]] & Align[SortedMap[K, *]] =
catsStdInstancesForSortedMap[K]
}
@@ -180,10 +204,7 @@ class SortedMapEq[K, V](implicit V: Eq[V], O: Order[K]) extends cats.kernel.inst
@deprecated("Use cats.kernel.instances.SortedMapCommutativeMonoid", "2.0.0-RC2")
class SortedMapCommutativeMonoid[K, V](implicit V: CommutativeSemigroup[V], O: Order[K])
extends SortedMapMonoid[K, V]
- with CommutativeMonoid[SortedMap[K, V]] {
- private[this] val underlying: CommutativeMonoid[SortedMap[K, V]] =
- new cats.kernel.instances.SortedMapCommutativeMonoid[K, V]
-}
+ with CommutativeMonoid[SortedMap[K, V]]
@deprecated("Use cats.kernel.instances.SortedMapMonoid", "2.0.0-RC2")
class SortedMapMonoid[K, V](implicit V: Semigroup[V], O: Order[K]) extends cats.kernel.instances.SortedMapMonoid[K, V]
diff --git a/core/src/main/scala/cats/instances/sortedSet.scala b/core/src/main/scala/cats/instances/sortedSet.scala
index 54ed34ea07..58df60337e 100644
--- a/core/src/main/scala/cats/instances/sortedSet.scala
+++ b/core/src/main/scala/cats/instances/sortedSet.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
@@ -7,7 +28,7 @@ import scala.annotation.tailrec
trait SortedSetInstances extends SortedSetInstances1 {
- implicit val catsStdInstancesForSortedSet: Foldable[SortedSet] with SemigroupK[SortedSet] =
+ implicit val catsStdInstancesForSortedSet: Foldable[SortedSet] & SemigroupK[SortedSet] =
new Foldable[SortedSet] with SemigroupK[SortedSet] {
def combineK[A](x: SortedSet[A], y: SortedSet[A]): SortedSet[A] = x | y
@@ -63,10 +84,7 @@ trait SortedSetInstances extends SortedSetInstances1 {
}
implicit def catsStdShowForSortedSet[A: Show]: Show[SortedSet[A]] =
- new Show[SortedSet[A]] {
- def show(fa: SortedSet[A]): String =
- fa.iterator.map(Show[A].show).mkString("SortedSet(", ", ", ")")
- }
+ _.iterator.map(Show[A].show).mkString("SortedSet(", ", ", ")")
@deprecated("Use cats.kernel.instances.sortedSet.catsKernelStdOrderForSortedSet", "2.0.0-RC2")
private[instances] def catsKernelStdOrderForSortedSet[A: Order]: Order[SortedSet[A]] =
diff --git a/core/src/main/scala/cats/instances/string.scala b/core/src/main/scala/cats/instances/string.scala
index a4c278464b..28da0fb39f 100644
--- a/core/src/main/scala/cats/instances/string.scala
+++ b/core/src/main/scala/cats/instances/string.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala/cats/instances/symbol/package.scala b/core/src/main/scala/cats/instances/symbol/package.scala
index 769d9fb97b..0bae34f9d8 100644
--- a/core/src/main/scala/cats/instances/symbol/package.scala
+++ b/core/src/main/scala/cats/instances/symbol/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala/cats/instances/tailrec.scala b/core/src/main/scala/cats/instances/tailrec.scala
index fc125a2ae4..7fb4fbe684 100644
--- a/core/src/main/scala/cats/instances/tailrec.scala
+++ b/core/src/main/scala/cats/instances/tailrec.scala
@@ -1,15 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
import scala.util.control.TailCalls.{done, tailcall, TailRec}
trait TailRecInstances {
- implicit def catsInstancesForTailRec: StackSafeMonad[TailRec] with Defer[TailRec] =
+ implicit def catsInstancesForTailRec: StackSafeMonad[TailRec] & Defer[TailRec] =
TailRecInstances.catsInstancesForTailRec
}
private object TailRecInstances {
- val catsInstancesForTailRec: StackSafeMonad[TailRec] with Defer[TailRec] =
+ val catsInstancesForTailRec: StackSafeMonad[TailRec] & Defer[TailRec] =
new StackSafeMonad[TailRec] with Defer[TailRec] {
def defer[A](fa: => TailRec[A]): TailRec[A] = tailcall(fa)
diff --git a/core/src/main/scala/cats/instances/try.scala b/core/src/main/scala/cats/instances/try.scala
index 5a88e4724b..8a69e752b1 100644
--- a/core/src/main/scala/cats/instances/try.scala
+++ b/core/src/main/scala/cats/instances/try.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
@@ -9,27 +30,27 @@ import scala.annotation.tailrec
trait TryInstances extends TryInstances1 {
- implicit def catsStdInstancesForTry: MonadThrow[Try] with CoflatMap[Try] with Traverse[Try] with Monad[Try] =
+ implicit def catsStdInstancesForTry: MonadThrow[Try] & CoflatMap[Try] & Traverse[Try] & Monad[Try] =
new TryCoflatMap with MonadThrow[Try] with Traverse[Try] with Monad[Try] {
def pure[A](x: A): Try[A] = Success(x)
override def product[A, B](ta: Try[A], tb: Try[B]): Try[(A, B)] =
(ta, tb) match {
case (Success(a), Success(b)) => Success((a, b))
- case (f: Failure[_], _) => castFailure[(A, B)](f)
- case (_, f: Failure[_]) => castFailure[(A, B)](f)
+ case (f: Failure[?], _) => castFailure[(A, B)](f)
+ case (_, f: Failure[?]) => castFailure[(A, B)](f)
}
override def map2[A, B, Z](ta: Try[A], tb: Try[B])(f: (A, B) => Z): Try[Z] =
(ta, tb) match {
case (Success(a), Success(b)) => Try(f(a, b))
- case (f: Failure[_], _) => castFailure[Z](f)
- case (_, f: Failure[_]) => castFailure[Z](f)
+ case (f: Failure[?], _) => castFailure[Z](f)
+ case (_, f: Failure[?]) => castFailure[Z](f)
}
override def map2Eval[A, B, Z](ta: Try[A], tb: Eval[Try[B]])(f: (A, B) => Z): Eval[Try[Z]] =
ta match {
- case f: Failure[_] => Now(castFailure[Z](f))
+ case f: Failure[?] => Now(castFailure[Z](f))
case Success(a) => tb.map(_.map(f(a, _)))
}
@@ -50,12 +71,21 @@ trait TryInstances extends TryInstances1 {
def traverse[G[_], A, B](fa: Try[A])(f: A => G[B])(implicit G: Applicative[G]): G[Try[B]] =
fa match {
case Success(a) => G.map(f(a))(Success(_))
- case f: Failure[_] => G.pure(castFailure[B](f))
+ case f: Failure[?] => G.pure(castFailure[B](f))
}
+ override def mapAccumulate[S, A, B](init: S, fa: Try[A])(f: (S, A) => (S, B)): (S, Try[B]) = {
+ fa match {
+ case Success(a) =>
+ val (snext, b) = f(init, a)
+ (snext, Success(b))
+ case f: Failure[?] => (init, castFailure[B](f))
+ }
+ }
+
@tailrec final def tailRecM[B, C](b: B)(f: B => Try[Either[B, C]]): Try[C] =
f(b) match {
- case f: Failure[_] => castFailure[C](f)
+ case f: Failure[?] => castFailure[C](f)
case Success(Left(b1)) => tailRecM(b1)(f)
case Success(Right(c)) => Success(c)
}
@@ -75,9 +105,11 @@ trait TryInstances extends TryInstances1 {
ta match { case Success(a) => Try(map(a)); case Failure(e) => Try(recover(e)) }
override def redeemWith[A, B](ta: Try[A])(recover: Throwable => Try[B], bind: A => Try[B]): Try[B] =
- try ta match {
- case Success(a) => bind(a); case Failure(e) => recover(e)
- } catch { case NonFatal(e) => Failure(e) }
+ try
+ ta match {
+ case Success(a) => bind(a); case Failure(e) => recover(e)
+ }
+ catch { case e if NonFatal(e) => Failure(e) }
override def recover[A](ta: Try[A])(pf: PartialFunction[Throwable, A]): Try[A] =
ta.recover(pf)
@@ -148,29 +180,18 @@ trait TryInstances extends TryInstances1 {
override def unit: Try[Unit] = successUnit
}
- implicit def catsStdShowForTry[A](implicit A: Show[A]): Show[Try[A]] =
- new Show[Try[A]] {
- def show(fa: Try[A]): String =
- fa match {
- case Success(a) => s"Success(${A.show(a)})"
- case Failure(e) => s"Failure($e)"
- }
- }
+ implicit def catsStdShowForTry[A](implicit A: Show[A]): Show[Try[A]] = {
+ case Success(a) => s"Success(${A.show(a)})"
+ case Failure(e) => s"Failure($e)"
+ }
/**
* you may wish to do equality by making `implicit val eqT: Eq[Throwable] = Eq.allEqual`
* doing a fine grained equality on Throwable can make the code very execution
* order dependent
*/
- implicit def catsStdEqForTry[A, T](implicit A: Eq[A], T: Eq[Throwable]): Eq[Try[A]] =
- new Eq[Try[A]] {
- def eqv(x: Try[A], y: Try[A]): Boolean =
- (x, y) match {
- case (Success(a), Success(b)) => A.eqv(a, b)
- case (Failure(a), Failure(b)) => T.eqv(a, b)
- case _ => false
- }
- }
+ implicit def catsStdEqForTry[A](implicit A: Eq[A], T: Eq[Throwable]): Eq[Try[A]] =
+ Eq.catsStdEqForTry
}
private[instances] object TryInstances {
@@ -179,7 +200,7 @@ private[instances] object TryInstances {
* A `Failure` can be statically typed as `Try[A]` for all `A`, because it
* does not actually contain an `A` value (as `Success[A]` does).
*/
- @inline final def castFailure[A](f: Failure[_]): Try[A] = f.asInstanceOf[Try[A]]
+ @inline final def castFailure[A](f: Failure[?]): Try[A] = f.asInstanceOf[Try[A]]
}
sealed private[instances] trait TryInstances1 extends TryInstances2 {
diff --git a/core/src/main/scala/cats/instances/tuple.scala b/core/src/main/scala/cats/instances/tuple.scala
index b74d9bbb1c..eb47d7bae4 100644
--- a/core/src/main/scala/cats/instances/tuple.scala
+++ b/core/src/main/scala/cats/instances/tuple.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
@@ -49,14 +70,12 @@ sealed private[instances] trait Tuple2Instances extends Tuple2Instances1 {
}
@deprecated("Use catsStdShowForTuple2 in cats.instances.NTupleShowInstances", "2.4.0")
- def catsStdShowForTuple2[A, B](implicit aShow: Show[A], bShow: Show[B]): Show[(A, B)] =
- new Show[(A, B)] {
- override def show(f: (A, B)): String =
- s"(${aShow.show(f._1)},${bShow.show(f._2)})"
- }
+ def catsStdShowForTuple2[A, B](implicit aShow: Show[A], bShow: Show[B]): Show[(A, B)] = { case (a, b) =>
+ s"(${aShow.show(a)},${bShow.show(b)})"
+ }
@deprecated("Use catsStdInstancesForTuple2 in cats.instances.NTupleMonadInstances", "2.4.0")
- def catsStdInstancesForTuple2[X]: Traverse[(X, *)] with Comonad[(X, *)] with Reducible[(X, *)] =
+ def catsStdInstancesForTuple2[X]: Traverse[(X, *)] & Comonad[(X, *)] & Reducible[(X, *)] =
new Traverse[(X, *)] with Comonad[(X, *)] with Reducible[(X, *)] {
def traverse[G[_], A, B](fa: (X, A))(f: A => G[B])(implicit G: Applicative[G]): G[(X, B)] =
G.map(f(fa._2))((fa._1, _))
@@ -67,6 +86,11 @@ sealed private[instances] trait Tuple2Instances extends Tuple2Instances1 {
override def map[A, B](fa: (X, A))(f: A => B): (X, B) = (fa._1, f(fa._2))
+ override def mapAccumulate[S, A, B](init: S, fa: (X, A))(f: (S, A) => (S, B)): (S, (X, B)) = {
+ val (snext, b) = f(init, fa._2)
+ (snext, (fa._1, b))
+ }
+
def coflatMap[A, B](fa: (X, A))(f: ((X, A)) => B): (X, B) = (fa._1, f(fa))
def extract[A](fa: (X, A)): A = fa._2
diff --git a/core/src/main/scala/cats/instances/uuid.scala b/core/src/main/scala/cats/instances/uuid.scala
index d01406d461..d516f88878 100644
--- a/core/src/main/scala/cats/instances/uuid.scala
+++ b/core/src/main/scala/cats/instances/uuid.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
diff --git a/core/src/main/scala/cats/instances/vector.scala b/core/src/main/scala/cats/instances/vector.scala
index 692f536015..161cddaf5f 100644
--- a/core/src/main/scala/cats/instances/vector.scala
+++ b/core/src/main/scala/cats/instances/vector.scala
@@ -1,23 +1,51 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package instances
-import cats.data.{Chain, ZipVector}
-import cats.syntax.show._
+import cats.data.{Chain, Ior, ZipVector}
+import cats.instances.StaticMethods.appendAll
+import cats.kernel.compat.scalaVersionSpecific._
import scala.annotation.tailrec
-import scala.collection.+:
import scala.collection.immutable.VectorBuilder
-import cats.data.Ior
trait VectorInstances extends cats.kernel.instances.VectorInstances {
implicit val catsStdInstancesForVector
- : Traverse[Vector] with Monad[Vector] with Alternative[Vector] with CoflatMap[Vector] with Align[Vector] =
+ : Traverse[Vector] & Monad[Vector] & Alternative[Vector] & CoflatMap[Vector] & Align[Vector] =
new Traverse[Vector] with Monad[Vector] with Alternative[Vector] with CoflatMap[Vector] with Align[Vector] {
def empty[A]: Vector[A] = Vector.empty[A]
def combineK[A](x: Vector[A], y: Vector[A]): Vector[A] = x ++ y
+ override def combineAllOptionK[A](as: IterableOnce[Vector[A]]): Option[Vector[A]] = {
+ val iter = as.iterator
+ if (iter.isEmpty) None else Some(appendAll(iter, Vector.newBuilder[A]).result())
+ }
+
+ override def fromIterableOnce[A](as: IterableOnce[A]): Vector[A] =
+ as.iterator.toVector
+
override def prependK[A](a: A, fa: Vector[A]): Vector[A] = a +: fa
override def appendK[A](fa: Vector[A], a: A): Vector[A] = fa :+ a
@@ -97,47 +125,68 @@ trait VectorInstances extends cats.kernel.instances.VectorInstances {
}
final override def traverse[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Vector[B]] =
- G.map(Chain.traverseViaChain(fa)(f))(_.toVector)
+ G match {
+ case x: StackSafeMonad[G] => x.map(Traverse.traverseDirectly(fa)(f)(x))(_.toVector)
+ case _ => G.map(Chain.traverseViaChain(fa)(f))(_.toVector)
+ }
+
+ final override def updated_[A, B >: A](fa: Vector[A], idx: Long, b: B): Option[Vector[B]] =
+ if (idx >= 0L && idx < fa.size.toLong) {
+ Some(fa.updated(idx.toInt, b))
+ } else {
+ None
+ }
/**
* This avoids making a very deep stack by building a tree instead
*/
- override def traverse_[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] = {
- // the cost of this is O(size)
- // c(n) = 1 + 2 * c(n/2)
- // invariant: size >= 1
- def runHalf(size: Int, idx: Int): Eval[G[Unit]] =
- if (size > 1) {
- val leftSize = size / 2
- val rightSize = size - leftSize
- runHalf(leftSize, idx)
- .flatMap { left =>
- val right = runHalf(rightSize, idx + leftSize)
- G.map2Eval(left, right) { (_, _) => () }
+ override def traverseVoid[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] = {
+ G match {
+ case x: StackSafeMonad[G] => Traverse.traverseVoidDirectly(fa)(f)(x)
+ case _ =>
+ // the cost of this is O(size)
+ // c(n) = 1 + 2 * c(n/2)
+ // invariant: size >= 1
+ def runHalf(size: Int, idx: Int): Eval[G[Unit]] =
+ if (size > 1) {
+ val leftSize = size / 2
+ val rightSize = size - leftSize
+ runHalf(leftSize, idx)
+ .flatMap { left =>
+ val right = runHalf(rightSize, idx + leftSize)
+ G.map2Eval(left, right) { (_, _) => () }
+ }
+ } else {
+ val a = fa(idx)
+ // we evaluate this at most one time,
+ // always is a bit cheaper in such cases
+ //
+ // Here is the point of the laziness using Eval:
+ // we avoid calling f(a) or G.void in the
+ // event that the computation has already
+ // failed. We do not use laziness to avoid
+ // traversing fa, which we will do fully
+ // in all cases.
+ Eval.always {
+ val gb = f(a)
+ G.void(gb)
+ }
}
- } else {
- val a = fa(idx)
- // we evaluate this at most one time,
- // always is a bit cheaper in such cases
- //
- // Here is the point of the laziness using Eval:
- // we avoid calling f(a) or G.void in the
- // event that the computation has already
- // failed. We do not use laziness to avoid
- // traversing fa, which we will do fully
- // in all cases.
- Eval.always {
- val gb = f(a)
- G.void(gb)
- }
- }
- val len = fa.length
- if (len == 0) G.unit
- else runHalf(len, 0).value
+ val len = fa.length
+ if (len == 0) G.unit
+ else runHalf(len, 0).value
+ }
}
+
+ override def mapAccumulate[S, A, B](init: S, fa: Vector[A])(f: (S, A) => (S, B)): (S, Vector[B]) =
+ StaticMethods.mapAccumulateFromStrictFunctor(init, fa, f)(this)
+
override def mapWithIndex[A, B](fa: Vector[A])(f: (A, Int) => B): Vector[B] =
- fa.iterator.zipWithIndex.map(ai => f(ai._1, ai._2)).toVector
+ StaticMethods.mapWithIndexFromStrictFunctor(fa, f)(this)
+
+ override def mapWithLongIndex[A, B](fa: Vector[A])(f: (A, Long) => B): Vector[B] =
+ StaticMethods.mapWithLongIndexFromStrictFunctor(fa, f)(this)
override def zipWithIndex[A](fa: Vector[A]): Vector[(A, Int)] =
fa.zipWithIndex
@@ -145,7 +194,8 @@ trait VectorInstances extends cats.kernel.instances.VectorInstances {
override def exists[A](fa: Vector[A])(p: A => Boolean): Boolean =
fa.exists(p)
- override def isEmpty[A](fa: Vector[A]): Boolean = fa.isEmpty
+ override def isEmpty[A](fa: Vector[A]): Boolean =
+ fa.isEmpty
override def foldM[G[_], A, B](fa: Vector[A], z: B)(f: (B, A) => G[B])(implicit G: Monad[G]): G[B] = {
val length = fa.length
@@ -166,7 +216,7 @@ trait VectorInstances extends cats.kernel.instances.VectorInstances {
override def find[A](fa: Vector[A])(f: A => Boolean): Option[A] = fa.find(f)
- override def algebra[A]: Monoid[Vector[A]] = new kernel.instances.VectorMonoid[A]
+ override def algebra[A]: Monoid[Vector[A]] = kernel.instances.VectorMonoid[A]
def functor: Functor[Vector] = this
@@ -186,10 +236,7 @@ trait VectorInstances extends cats.kernel.instances.VectorInstances {
}
implicit def catsStdShowForVector[A: Show]: Show[Vector[A]] =
- new Show[Vector[A]] {
- def show(fa: Vector[A]): String =
- fa.iterator.map(_.show).mkString("Vector(", ", ", ")")
- }
+ _.iterator.map(Show[A].show).mkString("Vector(", ", ", ")")
implicit def catsStdNonEmptyParallelForVectorZipVector: NonEmptyParallel.Aux[Vector, ZipVector] =
new NonEmptyParallel[Vector] {
@@ -206,6 +253,7 @@ trait VectorInstances extends cats.kernel.instances.VectorInstances {
}
}
+@suppressUnusedImportWarningForScalaVersionSpecific
private[instances] trait VectorInstancesBinCompat0 {
implicit val catsStdTraverseFilterForVector: TraverseFilter[Vector] = new TraverseFilter[Vector] {
val traverse: Traverse[Vector] = cats.instances.vector.catsStdInstancesForVector
@@ -222,7 +270,11 @@ private[instances] trait VectorInstancesBinCompat0 {
override def flattenOption[A](fa: Vector[Option[A]]): Vector[A] = fa.flatten
def traverseFilter[G[_], A, B](fa: Vector[A])(f: (A) => G[Option[B]])(implicit G: Applicative[G]): G[Vector[B]] =
- G.map(Chain.traverseFilterViaChain(fa)(f))(_.toVector)
+ G match {
+ case x: StackSafeMonad[G] => x.map(TraverseFilter.traverseFilterDirectly(fa)(f)(x))(_.toVector)
+ case _ =>
+ G.map(Chain.traverseFilterViaChain(fa)(f))(_.toVector)
+ }
override def filterA[G[_], A](fa: Vector[A])(f: (A) => G[Boolean])(implicit G: Applicative[G]): G[Vector[A]] =
traverse
diff --git a/core/src/main/scala/cats/package.scala b/core/src/main/scala/cats/package.scala
index 79c5c07101..0a86548034 100644
--- a/core/src/main/scala/cats/package.scala
+++ b/core/src/main/scala/cats/package.scala
@@ -1,35 +1,61 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
import scala.annotation.tailrec
+import cats.data.Ior
/**
* The `cats` root package contains all the trait signatures of most Scala type classes.
*
* Cats type classes are implemented using the approach from the
- * [[https://ropas.snu.ac.kr/~bruno/papers/TypeClasses.pdf Type classes as objects and implicits]] article.
+ * "[[https://i.cs.hku.hk/~bruno/papers/TypeClasses.pdf Type classes as objects and implicits]]" article.
*
- * For each type class, `cats` provides three pieces:
- * - Its '''signature''': a trait that is polymorphic on a type parameter.
- * Type class traits inherit from other type classes to indicate that any implementation of the lower type class (e.g. `Applicative`)
- * can also serve as an instance for the higuer type class (e.g. `Functor`).
- * - Type class ''''instances''', which are classes and objects that implement one or more type class signatures for some specific types.
- * Type class instances for several data types from the Java or Scala standard libraries are declared in the subpackage `cats.instances`.
- * - '''Syntax extensions''', each of which provides the methods of the type class defines as extension methods
- * (which in Scala 2 are encoded as implicit classes) for values of any type `F`; given that an instance of the type class
- * for the receiver type (`this`) is in the implicit scope.
- * Symtax extensions are declared in the `cats.syntax` package.
- * - A set of '''laws''', that are also generic on the type of the class, and are only defined on the operations of the type class.
- * The purpose of these laws is to declare some algebraic relations (equations) between Scala expressions involving the operations
- * of the type class, and test (but not verify) that implemented instances satisfy those equations.
- * Laws are defined in the `cats-laws` package.
+ * For each type class, `cats` provides four pieces:
+ * - Its '''signature''': a trait that is polymorphic on a type parameter.
+ * Type class traits inherit from other type classes to indicate that any implementation of the lower type class
+ * (e.g. [[Applicative `Applicative`]])
+ * can also serve as an instance for the higher type class (e.g. [[Functor `Functor`]]).
+ * - Type class '''instances''', which are classes and objects that implement one or more type class signatures for some specific types.
+ * Type class instances for several data types from the Java or Scala standard libraries are declared
+ * in the subpackage [[cats.instances `cats.instances`]].
+ * - '''Syntax extensions''', each of which provides the methods of the type class defined as extension methods
+ * (which in Scala 2 are encoded as implicit classes) for values of any type `F`; given that an instance of the type class
+ * for the receiver type (`this`) is in the implicit scope.
+ * Syntax extensions are declared in the [[cats.syntax `cats.syntax`]] package.
+ * - A set of '''laws''', that are also generic on the type of the class, and are only defined on the operations of the type class.
+ * The purpose of these laws is to declare some algebraic relations (equations) between Scala expressions involving the operations
+ * of the type class, and test (but not verify) that implemented instances satisfy those equations.
+ * Laws are defined in the [[cats.laws `cats.laws`]] package.
*
* Although most of cats type classes are declared in this package, some are declared in other packages:
- * - type classes that operate on base types (kind `*`), and their implementations for standard library types,
- * are contained in `cats.kernel`, which is a different SBT project. However, they are re-exported from this package.
- * - type classes of kind `F[_, _]`, such as [[cats.arrow.Profunctor]]" or [[cats.arrow.Arrow]], which are relevant for
- * Functional Reactive Programming or optics, are declared in the `cats.arrow` package.
- * - Also, those type classes that abstract over (pure or impure) functional runtime effects are declared
- * in the [[https://typelevel.org/cats-effect/ cats-effect library]].
- * - Some type classes for which no laws can be provided are left out of the main road, in a small and dirty alley.
- * These are the `alleycats`.
+ * - type classes that operate on base types (kind `*`), and their implementations for standard library types,
+ * are contained in [[cats.kernel `cats.kernel`]], which is a different SBT project. However, they are re-exported from this package.
+ * - type classes of kind `F[_, _]`,
+ * such as [[cats.arrow.Profunctor `cats.arrow.Profunctor`]] or [[cats.arrow.Arrow `cats.arrow.Arrow`]],
+ * which are relevant for
+ * Functional Reactive Programming or optics, are declared in the [[cats.arrow `cats.arrow`]] package.
+ * - Also, those type classes that abstract over (pure or impure) functional runtime effects are declared
+ * in the [[https://typelevel.org/cats-effect/ cats-effect library]].
+ * - Some type classes for which no laws can be provided are left out of the main road, in a small and dirty alley.
+ * These are the [[alleycats `alleycats`]].
*/
package object cats {
@@ -70,7 +96,7 @@ package object cats {
type Endo[A] = A => A
- val catsInstancesForId: Bimonad[Id] with CommutativeMonad[Id] with NonEmptyTraverse[Id] with Distributive[Id] =
+ val catsInstancesForId: Bimonad[Id] & CommutativeMonad[Id] & NonEmptyTraverse[Id] & Distributive[Id] =
new Bimonad[Id] with CommutativeMonad[Id] with NonEmptyTraverse[Id] with Distributive[Id] {
def pure[A](a: A): A = a
def extract[A](a: A): A = a
@@ -94,6 +120,8 @@ package object cats {
f(a, lb)
def nonEmptyTraverse[G[_], A, B](a: A)(f: A => G[B])(implicit G: Apply[G]): G[B] =
f(a)
+ override def mapAccumulate[S, A, B](init: S, fa: Id[A])(f: (S, A) => (S, B)): (S, Id[B]) =
+ f(init, fa)
override def foldMap[A, B](fa: Id[A])(f: A => B)(implicit B: Monoid[B]): B = f(fa)
override def reduce[A](fa: Id[A])(implicit A: Semigroup[A]): A =
fa
@@ -128,6 +156,13 @@ package object cats {
override def index[A](f: Id[A]): Unit => A = (_: Unit) => f
}
+ val catsAlignForId: Align[Id] = new Align[Id] {
+ override val functor: Functor[Id] = Functor[Id]
+
+ override def align[A, B](fa: Id[A], fb: Id[B]): Id[Ior[A, B]] = Ior.both(fa, fb)
+
+ }
+
implicit val catsParallelForId: Parallel.Aux[Id, Id] = Parallel.identity
type Eq[A] = cats.kernel.Eq[A]
diff --git a/core/src/main/scala/cats/syntax/DistributiveSyntax.scala b/core/src/main/scala/cats/syntax/DistributiveSyntax.scala
index a5ae364e38..b7125aea85 100644
--- a/core/src/main/scala/cats/syntax/DistributiveSyntax.scala
+++ b/core/src/main/scala/cats/syntax/DistributiveSyntax.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/TrySyntax.scala b/core/src/main/scala/cats/syntax/TrySyntax.scala
index 45e5d39e1f..c0632e3c5b 100644
--- a/core/src/main/scala/cats/syntax/TrySyntax.scala
+++ b/core/src/main/scala/cats/syntax/TrySyntax.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -16,7 +37,7 @@ final class TryOps[A](private val self: Try[A]) extends AnyVal {
* lift the `try` into a `F[_]` with `ApplicativeThrow[F]` instance
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import util.Try
*
* scala> val s: Try[Int] = Try(3)
diff --git a/core/src/main/scala/cats/syntax/align.scala b/core/src/main/scala/cats/syntax/align.scala
index bd41650f42..932e8f2d6b 100644
--- a/core/src/main/scala/cats/syntax/align.scala
+++ b/core/src/main/scala/cats/syntax/align.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/all.scala b/core/src/main/scala/cats/syntax/all.scala
index 8331f8bb64..60d6d2b150 100644
--- a/core/src/main/scala/cats/syntax/all.scala
+++ b/core/src/main/scala/cats/syntax/all.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/alternative.scala b/core/src/main/scala/cats/syntax/alternative.scala
index 15306fba01..a844042479 100644
--- a/core/src/main/scala/cats/syntax/alternative.scala
+++ b/core/src/main/scala/cats/syntax/alternative.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
trait AlternativeSyntax {
- // TODO: use simulacrum instances eventually
+
implicit final def catsSyntaxUnite[F[_], G[_], A](fga: F[G[A]]): UniteOps[F, G, A] =
new UniteOps[F, G, A](fga)
@@ -24,10 +45,10 @@ sealed private[syntax] trait UniteOpsBinCompat0[F[_], G[_], A] extends Any { sel
/**
* See [[[Alternative.unite[G[_],A](fga:F[G[A]])(implicitFM:cats\.FlatMap[F]*]]]
- *
+ *
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val x: List[Vector[Int]] = List(Vector(1, 2), Vector(3, 4))
* scala> x.unite
* res0: List[Int] = List(1, 2, 3, 4)
@@ -47,10 +68,10 @@ final class SeparateOps[F[_], G[_, _], A, B](protected val fgab: F[G[A, B]])
/**
* See [[Alternative.separateFoldable]]
- *
+ *
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val l: List[Either[String, Int]] = List(Right(1), Left("error"))
* scala> l.separateFoldable
* res0: (List[String], List[Int]) = (List(error),List(1))
@@ -64,10 +85,10 @@ sealed private[syntax] trait SeparateOpsBinCompat0[F[_], G[_, _], A, B] extends
/**
* See [[[Alternative.separate[G[_,_],A,B](fgab:F[G[A,B]])(implicitFM:cats\.FlatMap[F]* Alternative.separate]]]
- *
+ *
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val l: List[Either[String, Int]] = List(Right(1), Left("error"))
* scala> l.separate
* res0: (List[String], List[Int]) = (List(error),List(1))
@@ -81,10 +102,10 @@ final class GuardOps(private val condition: Boolean) extends AnyVal {
/**
* See [[Alternative.guard]]
- *
+ *
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> def even(i: Int): Option[String] = (i % 2 == 0).guard[Option].as("even")
* scala> even(2)
* res0: Option[String] = Some(even)
diff --git a/core/src/main/scala/cats/syntax/applicative.scala b/core/src/main/scala/cats/syntax/applicative.scala
index 4e2a271b02..9954f17922 100644
--- a/core/src/main/scala/cats/syntax/applicative.scala
+++ b/core/src/main/scala/cats/syntax/applicative.scala
@@ -1,10 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
trait ApplicativeSyntax {
implicit final def catsSyntaxApplicativeId[A](a: A): ApplicativeIdOps[A] =
new ApplicativeIdOps[A](a)
- implicit final def catsSyntaxApplicative[F[_], A](fa: F[A]): ApplicativeOps[F, A] =
+ implicit final def catsSyntaxApplicativeByName[F[_], A](fa: => F[A]): ApplicativeByNameOps[F, A] =
+ new ApplicativeByNameOps[F, A](() => fa)
+ implicit final def catsSyntaxApplicativeByValue[F[_], A](fa: F[A]): ApplicativeByValueOps[F, A] =
+ new ApplicativeByValueOps[F, A](fa)
+ @deprecated("Use by-value or by-name version", "2.8.0")
+ final def catsSyntaxApplicative[F[_], A](fa: F[A]): ApplicativeOps[F, A] =
new ApplicativeOps[F, A](fa)
}
@@ -12,8 +38,19 @@ final class ApplicativeIdOps[A](private val a: A) extends AnyVal {
def pure[F[_]](implicit F: Applicative[F]): F[A] = F.pure(a)
}
+@deprecated("Use by-value or by-name version", "2.8.0")
final class ApplicativeOps[F[_], A](private val fa: F[A]) extends AnyVal {
def replicateA(n: Int)(implicit F: Applicative[F]): F[List[A]] = F.replicateA(n, fa)
def unlessA(cond: Boolean)(implicit F: Applicative[F]): F[Unit] = F.unlessA(cond)(fa)
def whenA(cond: Boolean)(implicit F: Applicative[F]): F[Unit] = F.whenA(cond)(fa)
}
+
+final class ApplicativeByValueOps[F[_], A](private val fa: F[A]) extends AnyVal {
+ def replicateA(n: Int)(implicit F: Applicative[F]): F[List[A]] = F.replicateA(n, fa)
+ def replicateA_(n: Int)(implicit F: Applicative[F]): F[Unit] = F.replicateA_(n, fa)
+}
+
+final class ApplicativeByNameOps[F[_], A](private val fa: () => F[A]) extends AnyVal {
+ def unlessA(cond: Boolean)(implicit F: Applicative[F]): F[Unit] = F.unlessA(cond)(fa())
+ def whenA(cond: Boolean)(implicit F: Applicative[F]): F[Unit] = F.whenA(cond)(fa())
+}
diff --git a/core/src/main/scala/cats/syntax/applicativeError.scala b/core/src/main/scala/cats/syntax/applicativeError.scala
index b799f16e08..352658fc8e 100644
--- a/core/src/main/scala/cats/syntax/applicativeError.scala
+++ b/core/src/main/scala/cats/syntax/applicativeError.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -13,6 +34,11 @@ trait ApplicativeErrorSyntax {
fa: F[A]
)(implicit F: ApplicativeError[F, E]): ApplicativeErrorOps[F, E, A] =
new ApplicativeErrorOps[F, E, A](fa)
+
+ implicit final def catsSyntaxApplicativeErrorFUnit[F[_], E](
+ fu: F[Unit]
+ ): ApplicativeErrorFUnitOps[F, E] =
+ new ApplicativeErrorFUnitOps[F, E](fu)
}
/**
@@ -37,7 +63,7 @@ final private[syntax] class ApplicativeErrorExtensionOps[F[_], E](F: Applicative
}
final class ApplicativeErrorIdOps[E](private val e: E) extends AnyVal {
- def raiseError[F[_], A](implicit F: ApplicativeError[F, _ >: E]): F[A] =
+ def raiseError[F[_], A](implicit F: ApplicativeError[F, ? >: E]): F[A] =
F.raiseError(e)
}
@@ -122,3 +148,8 @@ final class ApplicativeErrorOps[F[_], E, A](private val fa: F[A]) extends AnyVal
def orRaise(other: => E)(implicit F: ApplicativeError[F, E]): F[A] =
adaptErr { case _ => other }
}
+
+final class ApplicativeErrorFUnitOps[F[_], E](private val fu: F[Unit]) extends AnyVal {
+ def voidError(implicit F: ApplicativeError[F, E]): F[Unit] =
+ F.voidError(fu)
+}
diff --git a/core/src/main/scala/cats/syntax/apply.scala b/core/src/main/scala/cats/syntax/apply.scala
index 3367e9c2b7..dcb0d95a67 100644
--- a/core/src/main/scala/cats/syntax/apply.scala
+++ b/core/src/main/scala/cats/syntax/apply.scala
@@ -1,8 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
-trait ApplySyntax extends TupleSemigroupalSyntax {
- implicit final def catsSyntaxApply[F[_], A](fa: F[A])(implicit F: Apply[F]): Apply.Ops[F, A] =
+trait ApplySyntax extends TupleSemigroupalSyntax with FunctionApplySyntax {
+ @deprecated("Kept for binary compatibility", "2.10.0")
+ final def catsSyntaxApply[F[_], A](fa: F[A], F: Apply[F]): Apply.Ops[F, A] =
new Apply.Ops[F, A] {
type TypeClassType = Apply[F]
@@ -10,6 +32,12 @@ trait ApplySyntax extends TupleSemigroupalSyntax {
val typeClassInstance = F
}
+ implicit final def catsSyntaxApplyFABOps[F[_], A, B](fab: F[A => B]): ApplyFABOps[F, A, B] =
+ new ApplyFABOps[F, A, B](fab)
+
+ implicit final def catsSyntaxApplyFABCOps[F[_], A, B, C](ff: F[(A, B) => C]): ApplyFABCOps[F, A, B, C] =
+ new ApplyFABCOps[F, A, B, C](ff)
+
implicit final def catsSyntaxApplyOps[F[_], A](fa: F[A]): ApplyOps[F, A] =
new ApplyOps(fa)
}
@@ -19,6 +47,73 @@ private[syntax] trait ApplySyntaxBinCompat0 {
new IfApplyOps[F](fa)
}
+final class ApplyFABOps[F[_], A, B](private val fab: F[A => B]) extends AnyVal {
+
+ /**
+ * @see [[Apply.ap]].
+ *
+ * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ *
+ * scala> val someF: Option[Int => Long] = Some(_.toLong + 1L)
+ * scala> val noneF: Option[Int => Long] = None
+ * scala> val someInt: Option[Int] = Some(3)
+ * scala> val noneInt: Option[Int] = None
+ *
+ * scala> someF.ap(someInt)
+ * res0: Option[Long] = Some(4)
+ *
+ * scala> noneF.ap(someInt)
+ * res1: Option[Long] = None
+ *
+ * scala> someF.ap(noneInt)
+ * res2: Option[Long] = None
+ *
+ * scala> noneF.ap(noneInt)
+ * res3: Option[Long] = None
+ * }}}
+ */
+ def ap(fa: F[A])(implicit F: Apply[F]): F[B] = F.ap(fab)(fa)
+
+ /**
+ * Alias for [[ap]].
+ */
+ def <*>(fa: F[A])(implicit F: Apply[F]): F[B] = F.<*>[A, B](fab)(fa)
+}
+
+final class ApplyFABCOps[F[_], A, B, C](private val ff: F[(A, B) => C]) extends AnyVal {
+
+ /**
+ * @see [[Apply.ap2]].
+ *
+ * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ *
+ * scala> val someF: Option[(Int, Int) => Long] = Some((a, b) => (a + b).toLong)
+ * scala> val noneF: Option[(Int, Int) => Long] = None
+ * scala> val someInt1: Option[Int] = Some(3)
+ * scala> val someInt2: Option[Int] = Some(2)
+ * scala> val noneInt: Option[Int] = None
+ *
+ * scala> someF.ap2(someInt1, someInt2)
+ * res0: Option[Long] = Some(5)
+ *
+ * scala> noneF.ap2(someInt1, someInt2)
+ * res1: Option[Long] = None
+ *
+ * scala> someF.ap2(noneInt, noneInt)
+ * res2: Option[Long] = None
+ *
+ * scala> noneF.ap2(noneInt, noneInt)
+ * res3: Option[Long] = None
+ * }}}
+ *
+ */
+ def ap2(fa: F[A], fb: F[B])(implicit F: Apply[F]): F[C] = F.ap2(ff)(fa, fb)
+}
+
final class IfApplyOps[F[_]](private val fcond: F[Boolean]) extends AnyVal {
@deprecated("Dangerous method, use ifM (a flatMap) or ifF (a map) instead", "2.6.2")
@@ -40,4 +135,122 @@ final class ApplyOps[F[_], A](private val fa: F[A]) extends AnyVal {
@deprecated("Use <* or productL instead.", "1.0.0-RC2")
@inline private[syntax] def forEffect[B](fb: F[B])(implicit F: Apply[F]): F[A] =
F.productL(fa)(fb)
+
+ /**
+ * @see [[Apply.productR]].
+ *
+ * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ * scala> import cats.data.Validated
+ * scala> import Validated.{Valid, Invalid}
+ *
+ * scala> type ErrOr[A] = Validated[String, A]
+ *
+ * scala> val validInt: ErrOr[Int] = Valid(3)
+ * scala> val validBool: ErrOr[Boolean] = Valid(true)
+ * scala> val invalidInt: ErrOr[Int] = Invalid("Invalid int.")
+ * scala> val invalidBool: ErrOr[Boolean] = Invalid("Invalid boolean.")
+ *
+ * scala> validInt.productR(validBool)
+ * res0: ErrOr[Boolean] = Valid(true)
+ *
+ * scala> invalidInt.productR(validBool)
+ * res1: ErrOr[Boolean] = Invalid(Invalid int.)
+ *
+ * scala> validInt.productR(invalidBool)
+ * res2: ErrOr[Boolean] = Invalid(Invalid boolean.)
+ *
+ * scala> invalidInt.productR(invalidBool)
+ * res3: ErrOr[Boolean] = Invalid(Invalid int.Invalid boolean.)
+ * }}}
+ */
+ def productR[B](fb: F[B])(implicit F: Apply[F]): F[B] = F.productR(fa)(fb)
+
+ /**
+ * @see [[Apply.productL]].
+ *
+ * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ * scala> import cats.data.Validated
+ * scala> import Validated.{Valid, Invalid}
+ *
+ * scala> type ErrOr[A] = Validated[String, A]
+ *
+ * scala> val validInt: ErrOr[Int] = Valid(3)
+ * scala> val validBool: ErrOr[Boolean] = Valid(true)
+ * scala> val invalidInt: ErrOr[Int] = Invalid("Invalid int.")
+ * scala> val invalidBool: ErrOr[Boolean] = Invalid("Invalid boolean.")
+ *
+ * scala> validInt.productL(validBool)
+ * res0: ErrOr[Int] = Valid(3)
+ *
+ * scala> invalidInt.productL(validBool)
+ * res1: ErrOr[Int] = Invalid(Invalid int.)
+ *
+ * scala> validInt.productL(invalidBool)
+ * res2: ErrOr[Int] = Invalid(Invalid boolean.)
+ *
+ * scala> invalidInt.productL(invalidBool)
+ * res3: ErrOr[Int] = Invalid(Invalid int.Invalid boolean.)
+ * }}}
+ */
+ def productL[B](fb: F[B])(implicit F: Apply[F]): F[A] = F.productL(fa)(fb)
+
+ /**
+ * Alias for [[productR]].
+ */
+ def *>[B](fb: F[B])(implicit F: Apply[F]): F[B] = F.*>(fa)(fb)
+
+ /**
+ * Alias for [[productL]].
+ */
+ def <*[B](fb: F[B])(implicit F: Apply[F]): F[A] = F.<*(fa)(fb)
+
+ /**
+ * @see [[Apply.map2]].
+ *
+ * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ *
+ * scala> val someInt: Option[Int] = Some(3)
+ * scala> val noneInt: Option[Int] = None
+ * scala> val someLong: Option[Long] = Some(4L)
+ * scala> val noneLong: Option[Long] = None
+ *
+ * scala> someInt.map2(someLong)((i, l) => i.toString + l.toString)
+ * res0: Option[String] = Some(34)
+ *
+ * scala> someInt.map2(noneLong)((i, l) => i.toString + l.toString)
+ * res0: Option[String] = None
+ *
+ * scala> noneInt.map2(noneLong)((i, l) => i.toString + l.toString)
+ * res0: Option[String] = None
+ *
+ * scala> noneInt.map2(someLong)((i, l) => i.toString + l.toString)
+ * res0: Option[String] = None
+ * }}}
+ */
+ def map2[B, C](fb: F[B])(f: (A, B) => C)(implicit F: Apply[F]): F[C] =
+ F.map2(fa, fb)(f)
+
+ /**
+ * @see [[Apply.map2Eval]].
+ *
+ * Example:
+ * {{{
+ * scala> import cats.{Eval, Later}
+ * scala> import cats.syntax.all._
+ *
+ * scala> val bomb: Eval[Option[Int]] = Later(sys.error("boom"))
+ * scala> val x: Option[Int] = None
+ *
+ * scala> x.map2Eval(bomb)(_ + _).value
+ * res0: Option[Int] = None
+ * }}}
+ */
+ def map2Eval[B, C](fb: Eval[F[B]])(f: (A, B) => C)(implicit F: Apply[F]): Eval[F[C]] =
+ F.map2Eval(fa, fb)(f)
}
diff --git a/core/src/main/scala/cats/syntax/arrow.scala b/core/src/main/scala/cats/syntax/arrow.scala
index 4498e36d85..19006fc52a 100644
--- a/core/src/main/scala/cats/syntax/arrow.scala
+++ b/core/src/main/scala/cats/syntax/arrow.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/arrowChoice.scala b/core/src/main/scala/cats/syntax/arrowChoice.scala
index 16adb051e9..b9fffe2893 100644
--- a/core/src/main/scala/cats/syntax/arrowChoice.scala
+++ b/core/src/main/scala/cats/syntax/arrowChoice.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/bifoldable.scala b/core/src/main/scala/cats/syntax/bifoldable.scala
index 09a8053df7..f74f220661 100644
--- a/core/src/main/scala/cats/syntax/bifoldable.scala
+++ b/core/src/main/scala/cats/syntax/bifoldable.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/bifunctor.scala b/core/src/main/scala/cats/syntax/bifunctor.scala
index 2daffa672e..1f2f9d4d4e 100644
--- a/core/src/main/scala/cats/syntax/bifunctor.scala
+++ b/core/src/main/scala/cats/syntax/bifunctor.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/binested.scala b/core/src/main/scala/cats/syntax/binested.scala
index 2963a59ba0..8905ba3e08 100644
--- a/core/src/main/scala/cats/syntax/binested.scala
+++ b/core/src/main/scala/cats/syntax/binested.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/bitraverse.scala b/core/src/main/scala/cats/syntax/bitraverse.scala
index b09661f267..9980880fa6 100644
--- a/core/src/main/scala/cats/syntax/bitraverse.scala
+++ b/core/src/main/scala/cats/syntax/bitraverse.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -42,7 +63,7 @@ final private[syntax] class BitraverseOpsBinCompat0[F[_, _], A, B](val fab: F[A,
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val intAndString: (Int, String) = (7, "test")
*
@@ -65,7 +86,7 @@ final class LeftNestedBitraverseOps[F[_, _], G[_], A, B](val fgab: F[G[A], B]) e
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val optionalErrorRight: Either[Option[String], Int] = Either.right(123)
* scala> optionalErrorRight.leftSequence
diff --git a/core/src/main/scala/cats/syntax/choice.scala b/core/src/main/scala/cats/syntax/choice.scala
index ba2df99594..a143c621ea 100644
--- a/core/src/main/scala/cats/syntax/choice.scala
+++ b/core/src/main/scala/cats/syntax/choice.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/coflatMap.scala b/core/src/main/scala/cats/syntax/coflatMap.scala
index 37d860ce1c..e271923eb8 100644
--- a/core/src/main/scala/cats/syntax/coflatMap.scala
+++ b/core/src/main/scala/cats/syntax/coflatMap.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/comonad.scala b/core/src/main/scala/cats/syntax/comonad.scala
index 1229e10dd1..ce133a6771 100644
--- a/core/src/main/scala/cats/syntax/comonad.scala
+++ b/core/src/main/scala/cats/syntax/comonad.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/compose.scala b/core/src/main/scala/cats/syntax/compose.scala
index 18649e7e85..f7f5c03652 100644
--- a/core/src/main/scala/cats/syntax/compose.scala
+++ b/core/src/main/scala/cats/syntax/compose.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/contravariant.scala b/core/src/main/scala/cats/syntax/contravariant.scala
index e721094822..819cd41d48 100644
--- a/core/src/main/scala/cats/syntax/contravariant.scala
+++ b/core/src/main/scala/cats/syntax/contravariant.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/contravariantMonoidal.scala b/core/src/main/scala/cats/syntax/contravariantMonoidal.scala
index 122f783065..ab5b76c754 100644
--- a/core/src/main/scala/cats/syntax/contravariantMonoidal.scala
+++ b/core/src/main/scala/cats/syntax/contravariantMonoidal.scala
@@ -1,12 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
import cats.ContravariantMonoidal
trait ContravariantMonoidalSyntax {
- implicit final def catsSyntaxContravariantMonoidal[F[_], A](
- fa: F[A]
- )(implicit F: ContravariantMonoidal[F]): ContravariantMonoidalOps[F, A] =
+ @deprecated("Kept for binary compatibility", "2.10.0")
+ final def catsSyntaxContravariantMonoidal[F[_], A](
+ fa: F[A],
+ F: ContravariantMonoidal[F]
+ ): ContravariantMonoidalOps[F, A] =
new ContravariantMonoidalOps[F, A] {
type TypeClassType = ContravariantMonoidal[F]
diff --git a/core/src/main/scala/cats/syntax/contravariantSemigroupal.scala b/core/src/main/scala/cats/syntax/contravariantSemigroupal.scala
index 0fc66f4999..29d92a4d26 100644
--- a/core/src/main/scala/cats/syntax/contravariantSemigroupal.scala
+++ b/core/src/main/scala/cats/syntax/contravariantSemigroupal.scala
@@ -1,12 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
import cats.ContravariantSemigroupal
trait ContravariantSemigroupalSyntax extends TupleSemigroupalSyntax {
- implicit final def catsSyntaxContravariantSemigroupal[F[_], A](
- fa: F[A]
- )(implicit F: ContravariantSemigroupal[F]): ContravariantSemigroupal.Ops[F, A] =
+ @deprecated("Kept for binary compatibility", "2.10.0")
+ final def catsSyntaxContravariantSemigroupal[F[_], A](
+ fa: F[A],
+ F: ContravariantSemigroupal[F]
+ ): ContravariantSemigroupal.Ops[F, A] =
new ContravariantSemigroupal.Ops[F, A] {
type TypeClassType = ContravariantSemigroupal[F]
diff --git a/core/src/main/scala/cats/syntax/either.scala b/core/src/main/scala/cats/syntax/either.scala
index 495133f68c..4c1ca96015 100644
--- a/core/src/main/scala/cats/syntax/either.scala
+++ b/core/src/main/scala/cats/syntax/either.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -173,6 +194,12 @@ final class EitherOps[A, B](private val eab: Either[A, B]) extends AnyVal {
case r @ Right(_) => EitherUtil.leftCast(r)
}
+ def leftMapOrKeep[AA >: A](pf: PartialFunction[A, AA]): Either[AA, B] =
+ eab match {
+ case Left(a) => Left(pf.applyOrElse(a, identity[AA]))
+ case r: Right[A, B] => r
+ }
+
@deprecated("Included in the standard library", "2.1.0-RC1")
private[syntax] def flatMap[AA >: A, D](f: B => Either[AA, D]): Either[AA, D] =
eab match {
@@ -186,6 +213,12 @@ final class EitherOps[A, B](private val eab: Either[A, B]) extends AnyVal {
case r @ Right(_) => EitherUtil.leftCast(r)
}
+ def leftFlatMapOrKeep[AA >: A, BB >: B](pfa: PartialFunction[A, Either[AA, BB]]): Either[AA, BB] =
+ eab match {
+ case l @ Left(a) => pfa.applyOrElse(a, (_: A) => l)
+ case r: Right[A, B] => r
+ }
+
def compare[AA >: A, BB >: B](that: Either[AA, BB])(implicit AA: Order[AA], BB: Order[BB]): Int =
eab match {
case Left(a1) =>
@@ -261,7 +294,7 @@ final class EitherOps[A, B](private val eab: Either[A, B]) extends AnyVal {
*
* Examples:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val l1: Either[String, Int] = Either.left("error 1")
* scala> val l2: Either[String, Int] = Either.left("error 2")
* scala> val r3: Either[String, Int] = Either.right(3)
@@ -302,7 +335,7 @@ final class EitherOps[A, B](private val eab: Either[A, B]) extends AnyVal {
* Transform the `Either` into a [[cats.data.EitherT]] while lifting it into the specified Applicative.
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val e: Either[String, Int] = Right(3)
* scala> e.toEitherT[Option]
* res0: cats.data.EitherT[Option, String, Int] = EitherT(Some(Right(3)))
@@ -324,14 +357,14 @@ final class EitherOps[A, B](private val eab: Either[A, B]) extends AnyVal {
* lift the `Either` into a `F[_]` with `ApplicativeError[F, A]` instance
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> import cats.data.EitherT
* scala> val e: Either[String, Int] = Right(3)
* scala> e.liftTo[EitherT[Option, CharSequence, *]]
* res0: cats.data.EitherT[Option, CharSequence, Int] = EitherT(Some(Right(3)))
* }}}
*/
- def liftTo[F[_]](implicit F: ApplicativeError[F, _ >: A]): F[B] = F.fromEither(eab)
+ def liftTo[F[_]](implicit F: ApplicativeError[F, ? >: A]): F[B] = F.fromEither(eab)
}
final class EitherObjectOps(private val either: Either.type) extends AnyVal {
@@ -357,7 +390,7 @@ final class EitherObjectOps(private val either: Either.type) extends AnyVal {
*
* For example:
* {{{
- * scala> import cats.implicits._ // get syntax for Either
+ * scala> import cats.syntax.all._ // get syntax for Either
* scala> Either.catchOnly[NumberFormatException] { "foo".toInt }
* res0: Either[NumberFormatException, Int] = Left(java.lang.NumberFormatException: For input string: "foo")
* }}}
@@ -369,7 +402,7 @@ final class EitherObjectOps(private val either: Either.type) extends AnyVal {
try {
right(f)
} catch {
- case scala.util.control.NonFatal(t) => left(t)
+ case t if scala.util.control.NonFatal(t) => left(t)
}
/**
@@ -395,6 +428,30 @@ final class EitherObjectOps(private val either: Either.type) extends AnyVal {
* Cached value of `Right(())` to avoid allocations for a common case.
*/
def unit[A]: Either[A, Unit] = EitherUtil.unit
+
+ /**
+ * Returns `Left(ifTrue)` when the `cond` is true, otherwise `Right(())`
+ *
+ * @example {{{
+ * val tooMany = 5
+ * val x: Int = ???
+ * Either.raiseWhen(x >= tooMany)(new IllegalArgumentException("Too many"))
+ * }}}
+ */
+ def raiseWhen[A](cond: Boolean)(ifTrue: => A): Either[A, Unit] =
+ ApplicativeError[Either[A, *], A].raiseWhen(cond)(ifTrue)
+
+ /**
+ * Returns `Left(ifFalse)` when `cond` is false, otherwise `Right(())`
+ *
+ * @example {{{
+ * val tooMany = 5
+ * val x: Int = ???
+ * Either.raiseUnless(x < tooMany)(new IllegalArgumentException("Too many"))
+ * }}}
+ */
+ def raiseUnless[A](cond: Boolean)(ifFalse: => A): Either[A, Unit] =
+ ApplicativeError[Either[A, *], A].raiseUnless(cond)(ifFalse)
}
final class LeftOps[A, B](private val left: Left[A, B]) extends AnyVal {
@@ -430,7 +487,7 @@ final class EitherIdOps[A](private val obj: A) extends AnyVal {
*
* For example:
* {{{
- * scala> import cats.implicits._, cats.data.NonEmptyList
+ * scala> import cats.syntax.all._, cats.data.NonEmptyList
* scala> "Err".leftNel[Int]
* res0: Either[NonEmptyList[String], Int] = Left(NonEmptyList(Err))
* }}}
@@ -442,7 +499,7 @@ final class EitherIdOps[A](private val obj: A) extends AnyVal {
*
* For example:
* {{{
- * scala> import cats.implicits._, cats.data.NonEmptyList
+ * scala> import cats.syntax.all._, cats.data.NonEmptyList
* scala> 1.rightNel[String]
* res0: Either[NonEmptyList[String], Int] = Right(1)
* }}}
@@ -466,7 +523,7 @@ final private[syntax] class EitherIdOpsBinCompat0[A](private val value: A) exten
*
* For example:
* {{{
- * scala> import cats.implicits._, cats.data.NonEmptyChain
+ * scala> import cats.syntax.all._, cats.data.NonEmptyChain
* scala> "Err".leftNec[Int]
* res0: Either[NonEmptyChain[String], Int] = Left(Chain(Err))
* }}}
@@ -478,7 +535,7 @@ final private[syntax] class EitherIdOpsBinCompat0[A](private val value: A) exten
*
* For example:
* {{{
- * scala> import cats.implicits._, cats.data.NonEmptyChain
+ * scala> import cats.syntax.all._, cats.data.NonEmptyChain
* scala> 1.rightNec[String]
* res0: Either[NonEmptyChain[String], Int] = Right(1)
* }}}
diff --git a/core/src/main/scala/cats/syntax/eitherK.scala b/core/src/main/scala/cats/syntax/eitherK.scala
index 0e0983cdda..0cabf0dce3 100644
--- a/core/src/main/scala/cats/syntax/eitherK.scala
+++ b/core/src/main/scala/cats/syntax/eitherK.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -18,7 +39,7 @@ final class EitherKOps[F[_], A](private val fa: F[A]) extends AnyVal {
* {{{
* scala> import cats.data.EitherK
* scala> import cats.Eval
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> List(1, 2, 3).leftc[Eval]
* res0: EitherK[List, Eval, Int] = EitherK(Left(List(1, 2, 3)))
* }}}
@@ -34,7 +55,7 @@ final class EitherKOps[F[_], A](private val fa: F[A]) extends AnyVal {
* {{{
* scala> import cats.data.EitherK
* scala> import cats.Eval
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> List(1, 2, 3).rightc[Eval]
* res0: EitherK[Eval, List, Int] = EitherK(Right(List(1, 2, 3)))
* }}}
diff --git a/core/src/main/scala/cats/syntax/eq.scala b/core/src/main/scala/cats/syntax/eq.scala
index 29f9c8f4ef..f6fa3fde5b 100644
--- a/core/src/main/scala/cats/syntax/eq.scala
+++ b/core/src/main/scala/cats/syntax/eq.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/flatMap.scala b/core/src/main/scala/cats/syntax/flatMap.scala
index 93d1b94c58..9791f47450 100644
--- a/core/src/main/scala/cats/syntax/flatMap.scala
+++ b/core/src/main/scala/cats/syntax/flatMap.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -64,7 +85,7 @@ final class FlattenOps[F[_], A](private val ffa: F[F[A]]) extends AnyVal {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> type ErrorOr[A] = Either[String, A]
* scala> val x: ErrorOr[ErrorOr[Int]] = 3.asRight.asRight
* scala> x.flatten
@@ -82,7 +103,7 @@ final class IfMOps[F[_]](private val fa: F[Boolean]) extends AnyVal {
* Example:
* {{{
* scala> import cats.{Eval, Now}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val b1: Eval[Boolean] = Now(true)
* scala> val asInt1: Eval[Int] = b1.ifM(Now(1), Now(0))
@@ -103,7 +124,7 @@ final class FlatMapIdOps[A](private val a: A) extends AnyVal {
/**
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val a: Int = 10
* scala> a.tailRecM[Option,String](i => if (i == 20) Some(Right("done")) else Some(Left(i+1)))
diff --git a/core/src/main/scala/cats/syntax/foldable.scala b/core/src/main/scala/cats/syntax/foldable.scala
index 9bd3c351fa..b70eb71674 100644
--- a/core/src/main/scala/cats/syntax/foldable.scala
+++ b/core/src/main/scala/cats/syntax/foldable.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -6,7 +27,11 @@ trait FoldableSyntax extends Foldable.ToFoldableOps with UnorderedFoldable.ToUno
implicit final def catsSyntaxNestedFoldable[F[_]: Foldable, G[_], A](fga: F[G[A]]): NestedFoldableOps[F, G, A] =
new NestedFoldableOps[F, G, A](fga)
- implicit final def catsSyntaxFoldOps[F[_]: Foldable, A](fa: F[A]): FoldableOps[F, A] =
+ implicit final def catsSyntaxFoldOps[F[_], A](fa: F[A]): FoldableOps[F, A] =
+ new FoldableOps[F, A](fa)
+
+ @deprecated("Use overload without Foldable parameter", "2.9.0")
+ final def catsSyntaxFoldOps[F[_], A](fa: F[A], F: Foldable[F]): FoldableOps[F, A] =
new FoldableOps[F, A](fa)
}
@@ -22,20 +47,25 @@ private[syntax] trait FoldableSyntaxBinCompat1 {
}
final class NestedFoldableOps[F[_], G[_], A](private val fga: F[G[A]]) extends AnyVal {
- def sequence_(implicit F: Foldable[F], G: Applicative[G]): G[Unit] = F.sequence_(fga)
+ // TODO: looks like these two methods below duplicate the same named methods from `Foldable.Ops`.
+ // Perhaps it makes sense to deprecate one pair of them either here or there.
+ def sequenceVoid(implicit F: Foldable[F], G: Applicative[G]): G[Unit] = F.sequenceVoid(fga)
+ def sequence_(implicit F: Foldable[F], G: Applicative[G]): G[Unit] = sequenceVoid
/**
* @see [[Foldable.foldK]].
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val l: List[Set[Int]] = List(Set(1, 2), Set(2, 3), Set(3, 4))
* scala> l.foldK
* res0: Set[Int] = Set(1, 2, 3, 4)
* }}}
*/
+ // TODO: looks like this method below duplicate the same named one from `Foldable.Ops`.
+ // Perhaps it makes sense to deprecate one of them.
def foldK(implicit F: Foldable[F], G: MonoidK[G]): G[A] = F.foldK(fga)
}
@@ -49,29 +79,15 @@ final class FoldableOps[F[_], A](private val fa: F[A]) extends AnyVal {
def foldA[G[_], B](implicit F: Foldable[F], ev: A <:< G[B], G: Applicative[G], B: Monoid[B]): G[B] =
F.foldA[G, B](fa.asInstanceOf[F[G[B]]])
- /**
- * test if `F[A]` contains an `A`, named contains_ to avoid conflict with existing contains which uses universal equality
- *
- * Example:
- * {{{
- * scala> import cats.implicits._
- *
- * scala> val l: List[Int] = List(1, 2, 3, 4)
- * scala> l.contains_(1)
- * res0: Boolean = true
- * scala> l.contains_(5)
- * res1: Boolean = false
- * }}}
- */
- def contains_(v: A)(implicit ev: Eq[A], F: Foldable[F]): Boolean =
- F.exists(fa)(ev.eqv(_, v))
+ private[syntax] def contains_(v: A, eq: Eq[A], F: Foldable[F]): Boolean =
+ F.contains_(fa, v)(eq)
/**
* Intercalate with a prefix and a suffix
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val l: List[String] = List("1", "2", "3")
* scala> l.foldSmash("List(", ",", ")")
@@ -88,7 +104,7 @@ final class FoldableOps[F[_], A](private val fa: F[A]) extends AnyVal {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val l: List[Int] = List(1, 2, 3)
* scala> l.mkString_("L[", ";", "]")
@@ -118,7 +134,7 @@ final class FoldableOps[F[_], A](private val fa: F[A]) extends AnyVal {
*
* For example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> def parseInt(s: String): Either[String, Int] = Either.catchOnly[NumberFormatException](s.toInt).leftMap(_.getMessage)
* scala> val keys1 = List("1", "2", "4", "5")
* scala> val map1 = Map(4 -> "Four", 5 -> "Five")
@@ -149,7 +165,7 @@ final class FoldableOps[F[_], A](private val fa: F[A]) extends AnyVal {
*
* For example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val list = List(1,2,3,4)
* scala> list.findM(n => (n >= 2).asRight[String])
* res0: Either[String,Option[Int]] = Right(Some(2))
@@ -164,23 +180,25 @@ final class FoldableOps[F[_], A](private val fa: F[A]) extends AnyVal {
* res3: Either[String,Option[Int]] = Left(error)
* }}}
*/
- def findM[G[_]](p: A => G[Boolean])(implicit F: Foldable[F], G: Monad[G]): G[Option[A]] = F.findM[G, A](fa)(p)
+ def findM[G[_]](p: A => G[Boolean])(implicit F: Foldable[F], G: Monad[G]): G[Option[A]] =
+ F.findM[G, A](fa)(p)
/**
* Tear down a subset of this structure using a `PartialFunction`.
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val xs = List(1, 2, 3, 4)
* scala> xs.collectFold { case n if n % 2 == 0 => n }
* res0: Int = 6
* }}}
*/
- def collectFold[M](f: PartialFunction[A, M])(implicit F: Foldable[F], M: Monoid[M]): M = F.collectFold[A, M](fa)(f)
+ def collectFold[M](f: PartialFunction[A, M])(implicit F: Foldable[F], M: Monoid[M]): M =
+ F.collectFold[A, M](fa)(f)
/**
* Tear down a subset of this structure using a `A => Option[M]`.
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val xs = List(1, 2, 3, 4)
* scala> def f(n: Int): Option[Int] = if (n % 2 == 0) Some(n) else None
* scala> xs.collectFoldSome(f)
@@ -188,7 +206,8 @@ final class FoldableOps[F[_], A](private val fa: F[A]) extends AnyVal {
* }}}
*/
@deprecated("Use collectFoldSome", "2.1.0-RC1")
- def collectSomeFold[M](f: A => Option[M])(implicit F: Foldable[F], M: Monoid[M]): M = F.collectFoldSome[A, M](fa)(f)
+ def collectSomeFold[M](f: A => Option[M])(implicit F: Foldable[F], M: Monoid[M]): M =
+ F.collectFoldSome[A, M](fa)(f)
}
final class FoldableOps0[F[_], A](private val fa: F[A]) extends AnyVal {
@@ -200,7 +219,7 @@ final class FoldableOps0[F[_], A](private val fa: F[A]) extends AnyVal {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val l: List[Int] = List(1, 2, 3)
* scala> l.mkString_(",")
@@ -218,21 +237,22 @@ final class FoldableOps0[F[_], A](private val fa: F[A]) extends AnyVal {
* combining them using the `MonoidK[G]` instance.
*
* {{{
- * scala> import cats._, cats.implicits._
+ * scala> import cats._, cats.syntax.all._
* scala> val f: Int => Endo[String] = i => (s => s + i)
* scala> val x: Endo[String] = List(1, 2, 3).foldMapK(f)
* scala> val a = x("foo")
* a: String = "foo321"
* }}}
*/
- def foldMapK[G[_], B](f: A => G[B])(implicit F: Foldable[F], G: MonoidK[G]): G[B] = F.foldMapK(fa)(f)
+ def foldMapK[G[_], B](f: A => G[B])(implicit F: Foldable[F], G: MonoidK[G]): G[B] =
+ F.foldMapK(fa)(f)
/**
* Separate this Foldable into a Tuple by an effectful separating function `A => H[B, C]` for some `Bifoldable[H]`
* Equivalent to `Functor#map` over `Alternative#separate`
*
* {{{
- * scala> import cats.implicits._, cats.data.Const
+ * scala> import cats.syntax.all._, cats.data.Const
* scala> val list = List(1,2,3,4)
* scala> list.partitionBifold(a => (a, "value " + a.toString))
* res0: (List[Int], List[String]) = (List(1, 2, 3, 4),List(value 1, value 2, value 3, value 4))
@@ -251,7 +271,7 @@ final class FoldableOps0[F[_], A](private val fa: F[A]) extends AnyVal {
* Equivalent to `Traverse#traverse` over `Alternative#separate`
*
* {{{
- * scala> import cats.implicits._, cats.data.Const
+ * scala> import cats.syntax.all._, cats.data.Const
* scala> val list = List(1,2,3,4)
* `Const`'s second parameter is never instantiated, so we can use an impossible type:
* scala> list.partitionBifoldM(a => Option(Const[Int, Nothing with Any](a)))
@@ -268,7 +288,7 @@ final class FoldableOps0[F[_], A](private val fa: F[A]) extends AnyVal {
* Equivalent to `Traverse#traverse` over `Alternative#separate`
*
* {{{
- * scala> import cats.implicits._, cats.Eval
+ * scala> import cats.syntax.all._, cats.Eval
* scala> val list = List(1,2,3,4)
* scala> val partitioned1 = list.partitionEitherM(a => if (a % 2 == 0) Eval.now(Either.left[String, Int](a.toString)) else Eval.now(Either.right[String, Int](a)))
* Since `Eval.now` yields a lazy computation, we need to force it to inspect the result:
@@ -284,23 +304,40 @@ final class FoldableOps0[F[_], A](private val fa: F[A]) extends AnyVal {
)(implicit A: Alternative[F], F: Foldable[F], M: Monad[G]): G[(F[B], F[C])] =
F.partitionEitherM[G, A, B, C](fa)(f)(A, M)
- def sliding2(implicit F: Foldable[F]): List[(A, A)] = F.sliding2(fa)
- def sliding3(implicit F: Foldable[F]): List[(A, A, A)] = F.sliding3(fa)
- def sliding4(implicit F: Foldable[F]): List[(A, A, A, A)] = F.sliding4(fa)
- def sliding5(implicit F: Foldable[F]): List[(A, A, A, A, A)] = F.sliding5(fa)
- def sliding6(implicit F: Foldable[F]): List[(A, A, A, A, A, A)] = F.sliding6(fa)
- def sliding7(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A)] = F.sliding7(fa)
- def sliding8(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A)] = F.sliding8(fa)
- def sliding9(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A)] = F.sliding9(fa)
- def sliding10(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A)] = F.sliding10(fa)
- def sliding11(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A)] = F.sliding11(fa)
- def sliding12(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A)] = F.sliding12(fa)
- def sliding13(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A)] = F.sliding13(fa)
- def sliding14(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A)] = F.sliding14(fa)
- def sliding15(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)] = F.sliding15(fa)
- def sliding16(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)] = F.sliding16(fa)
- def sliding17(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)] = F.sliding17(fa)
- def sliding18(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)] = F.sliding18(fa)
+ def sliding2(implicit F: Foldable[F]): List[(A, A)] =
+ F.sliding2(fa)
+ def sliding3(implicit F: Foldable[F]): List[(A, A, A)] =
+ F.sliding3(fa)
+ def sliding4(implicit F: Foldable[F]): List[(A, A, A, A)] =
+ F.sliding4(fa)
+ def sliding5(implicit F: Foldable[F]): List[(A, A, A, A, A)] =
+ F.sliding5(fa)
+ def sliding6(implicit F: Foldable[F]): List[(A, A, A, A, A, A)] =
+ F.sliding6(fa)
+ def sliding7(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A)] =
+ F.sliding7(fa)
+ def sliding8(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A)] =
+ F.sliding8(fa)
+ def sliding9(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A)] =
+ F.sliding9(fa)
+ def sliding10(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A)] =
+ F.sliding10(fa)
+ def sliding11(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A)] =
+ F.sliding11(fa)
+ def sliding12(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A)] =
+ F.sliding12(fa)
+ def sliding13(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A)] =
+ F.sliding13(fa)
+ def sliding14(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A)] =
+ F.sliding14(fa)
+ def sliding15(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)] =
+ F.sliding15(fa)
+ def sliding16(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)] =
+ F.sliding16(fa)
+ def sliding17(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)] =
+ F.sliding17(fa)
+ def sliding18(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)] =
+ F.sliding18(fa)
def sliding19(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)] =
F.sliding19(fa)
def sliding20(implicit F: Foldable[F]): List[(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)] =
diff --git a/core/src/main/scala/cats/syntax/function1.scala b/core/src/main/scala/cats/syntax/function1.scala
index 7ec5ae0b1d..7b4b74c7a5 100644
--- a/core/src/main/scala/cats/syntax/function1.scala
+++ b/core/src/main/scala/cats/syntax/function1.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -17,7 +38,7 @@ trait Function1Syntax {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val someF: Option[Int => Long] = Some(_.toLong + 1L)
* scala> val noneF: Option[Int => Long] = None
@@ -42,7 +63,7 @@ trait Function1Syntax {
* Example:
* {{{
* scala> import scala.util._
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val f: List[String] => Option[String] = _.headOption
* scala> val g: String => Option[Int] = str => Try(str.toInt).toOption
@@ -67,7 +88,7 @@ trait Function1Syntax {
* Example:
* {{{
* scala> import scala.util._
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val f: String => Option[Int] = str => Try(str.toInt).toOption
* scala> val g: List[String] => Option[String] = _.headOption
diff --git a/core/src/main/scala/cats/syntax/functor.scala b/core/src/main/scala/cats/syntax/functor.scala
index fe9ff040ff..41a9541471 100644
--- a/core/src/main/scala/cats/syntax/functor.scala
+++ b/core/src/main/scala/cats/syntax/functor.scala
@@ -1,9 +1,33 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
trait FunctorSyntax extends Functor.ToFunctorOps {
implicit final def catsSyntaxFunctorTuple2Ops[F[_], A, B](fab: F[(A, B)]): FunctorTuple2Ops[F, A, B] =
new FunctorTuple2Ops[F, A, B](fab)
+
+ implicit final def catsSyntaxIfF[F[_]](fa: F[Boolean]): IfFOps[F] =
+ new IfFOps[F](fa)
}
final class FunctorTuple2Ops[F[_], A, B](private val fab: F[(A, B)]) extends AnyVal {
@@ -62,3 +86,19 @@ final class FunctorTuple2Ops[F[_], A, B](private val fab: F[(A, B)]) extends Any
*/
def unzip(implicit F: Functor[F]): (F[A], F[B]) = F.unzip(fab)
}
+
+final class IfFOps[F[_]](private val fa: F[Boolean]) extends AnyVal {
+
+ /**
+ * Lifts `if` to Functor
+ *
+ * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ *
+ * scala> List(true, false, false).ifF(1, 0)
+ * res0: List[Int] = List(1, 0, 0)
+ * }}}
+ */
+ def ifF[B](ifTrue: => B, ifFalse: => B)(implicit F: Functor[F]): F[B] = F.ifF(fa)(ifTrue, ifFalse)
+}
diff --git a/core/src/main/scala/cats/syntax/functorFilter.scala b/core/src/main/scala/cats/syntax/functorFilter.scala
index a80b6c2618..07290fed53 100644
--- a/core/src/main/scala/cats/syntax/functorFilter.scala
+++ b/core/src/main/scala/cats/syntax/functorFilter.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/group.scala b/core/src/main/scala/cats/syntax/group.scala
index f8214d42ea..bc07c921d7 100644
--- a/core/src/main/scala/cats/syntax/group.scala
+++ b/core/src/main/scala/cats/syntax/group.scala
@@ -1,8 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
trait GroupSyntax extends SemigroupSyntax {
- // TODO: use simulacrum instances eventually
implicit final def catsSyntaxGroup[A: Group](a: A): GroupOps[A] =
new GroupOps[A](a)
}
diff --git a/core/src/main/scala/cats/syntax/hash.scala b/core/src/main/scala/cats/syntax/hash.scala
index ff2595f2d4..016650cce9 100644
--- a/core/src/main/scala/cats/syntax/hash.scala
+++ b/core/src/main/scala/cats/syntax/hash.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/invariant.scala b/core/src/main/scala/cats/syntax/invariant.scala
index 7ae1f32542..083274fe64 100644
--- a/core/src/main/scala/cats/syntax/invariant.scala
+++ b/core/src/main/scala/cats/syntax/invariant.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/ior.scala b/core/src/main/scala/cats/syntax/ior.scala
index 80a870341d..497ad73532 100644
--- a/core/src/main/scala/cats/syntax/ior.scala
+++ b/core/src/main/scala/cats/syntax/ior.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.syntax
import cats.data.Ior
@@ -14,7 +35,7 @@ final class IorIdOps[A](private val a: A) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "hello".rightIor[String]
* res0: Ior[String, String] = Right(hello)
@@ -28,7 +49,7 @@ final class IorIdOps[A](private val a: A) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> "error".leftIor[String]
* res0: Ior[String, String] = Left(error)
diff --git a/core/src/main/scala/cats/syntax/list.scala b/core/src/main/scala/cats/syntax/list.scala
index f1878ec29e..bbbc635795 100644
--- a/core/src/main/scala/cats/syntax/list.scala
+++ b/core/src/main/scala/cats/syntax/list.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -16,7 +37,7 @@ final class ListOps[A](private val la: List[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.NonEmptyList
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: List[Int] = List(1, 2)
* scala> result1.toNel
@@ -36,7 +57,7 @@ final class ListOps[A](private val la: List[A]) extends AnyVal {
* {{{
* scala> import cats.data.NonEmptyList
* scala> import scala.collection.immutable.SortedMap
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val list = List(12, -2, 3, -5)
*
@@ -58,7 +79,7 @@ final class ListOps[A](private val la: List[A]) extends AnyVal {
* {{{
* scala> import cats.data.NonEmptyList
* scala> import scala.collection.immutable.SortedMap
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val list = List(12, -2, 3, -5)
*
@@ -84,7 +105,7 @@ final class ListOps[A](private val la: List[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.NonEmptyList
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: List[Int] = List(1, 2)
* scala> result1.scanLeftNel(100)(_ + _)
@@ -105,7 +126,7 @@ final class ListOps[A](private val la: List[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.NonEmptyList
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: List[Int] = List(1, 2)
* scala> result1.scanRightNel(100)(_ + _)
@@ -133,7 +154,7 @@ final private[syntax] class ListOpsBinCompat0[A](private val la: List[A]) extend
* {{{
* scala> import cats.data.NonEmptyChain
* scala> import scala.collection.immutable.SortedMap
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val list = List(12, -2, 3, -5)
*
diff --git a/core/src/main/scala/cats/syntax/monad.scala b/core/src/main/scala/cats/syntax/monad.scala
index 396d06b561..656c9bcb00 100644
--- a/core/src/main/scala/cats/syntax/monad.scala
+++ b/core/src/main/scala/cats/syntax/monad.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/monadError.scala b/core/src/main/scala/cats/syntax/monadError.scala
index fa75dff02f..5b13b52059 100644
--- a/core/src/main/scala/cats/syntax/monadError.scala
+++ b/core/src/main/scala/cats/syntax/monadError.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -7,7 +28,7 @@ trait MonadErrorSyntax {
implicit final def catsSyntaxMonadErrorRethrow[F[_], E, A](
fea: F[Either[E, A]]
- )(implicit F: MonadError[F, _ >: E]): MonadErrorRethrowOps[F, E, A] =
+ )(implicit F: MonadError[F, ? >: E]): MonadErrorRethrowOps[F, E, A] =
new MonadErrorRethrowOps(fea)
}
@@ -38,7 +59,7 @@ final class MonadErrorOps[F[_], E, A](private val fa: F[A]) extends AnyVal {
}
final class MonadErrorRethrowOps[F[_], E, A](private val fea: F[Either[E, A]]) extends AnyVal {
- def rethrow(implicit F: MonadError[F, _ >: E]): F[A] =
+ def rethrow(implicit F: MonadError[F, ? >: E]): F[A] =
F.flatMap(fea)(
_.fold(F.raiseError, F.pure)
) // dup from the type class impl, due to https://github.com/scala/bug/issues/11562. Once fixed should be able to replace with `F.rethrow(fea)`
diff --git a/core/src/main/scala/cats/syntax/monoid.scala b/core/src/main/scala/cats/syntax/monoid.scala
index 4d7c2b9d29..513c0e0ef3 100644
--- a/core/src/main/scala/cats/syntax/monoid.scala
+++ b/core/src/main/scala/cats/syntax/monoid.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
trait MonoidSyntax extends SemigroupSyntax {
- // TODO: use simulacrum instances eventually
+
implicit final def catsSyntaxMonoid[A: Monoid](a: A): MonoidOps[A] =
new MonoidOps[A](a)
}
diff --git a/core/src/main/scala/cats/syntax/nested.scala b/core/src/main/scala/cats/syntax/nested.scala
index 9db2163d80..cdc0df66f4 100644
--- a/core/src/main/scala/cats/syntax/nested.scala
+++ b/core/src/main/scala/cats/syntax/nested.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -17,7 +38,7 @@ final class NestedIdOps[F[_], G[_], A](private val value: F[G[A]]) extends AnyVa
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> List(Some(3), None).nested.map(_+1).value
* res0: List[Option[Int]] = List(Some(4), None)
* }}}
diff --git a/core/src/main/scala/cats/syntax/nonEmptyAlternative.scala b/core/src/main/scala/cats/syntax/nonEmptyAlternative.scala
index 1f8d1bd669..ad5f830992 100644
--- a/core/src/main/scala/cats/syntax/nonEmptyAlternative.scala
+++ b/core/src/main/scala/cats/syntax/nonEmptyAlternative.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/nonEmptyTraverse.scala b/core/src/main/scala/cats/syntax/nonEmptyTraverse.scala
index 5c6fe63b36..6b84973bef 100644
--- a/core/src/main/scala/cats/syntax/nonEmptyTraverse.scala
+++ b/core/src/main/scala/cats/syntax/nonEmptyTraverse.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/option.scala b/core/src/main/scala/cats/syntax/option.scala
index 3550377fcc..16cc8a3270 100644
--- a/core/src/main/scala/cats/syntax/option.scala
+++ b/core/src/main/scala/cats/syntax/option.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -30,7 +51,7 @@ final class OptionIdOps[A](private val a: A) extends AnyVal {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> 3.some
* res0: Option[Int] = Some(3)
* }}}
@@ -48,7 +69,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.Validated
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val error1: Option[String] = Some("error!")
* scala> error1.toInvalid(3)
@@ -70,7 +91,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.ValidatedNel
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val error1: Option[String] = Some("error!")
* scala> error1.toInvalidNel(3)
@@ -93,7 +114,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.ValidatedNec
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val error1: Option[String] = Some("error!")
* scala> error1.toInvalidNec(3)
@@ -115,7 +136,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.Validated
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: Option[Int] = Some(3)
* scala> result1.toValid("error!")
@@ -136,7 +157,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.ValidatedNel
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: Option[Int] = Some(3)
* scala> result1.toValidNel("error!")
@@ -158,7 +179,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.ValidatedNec
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: Option[Int] = Some(3)
* scala> result1.toValidNec("error!")
@@ -179,7 +200,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: Option[Int] = Some(3)
* scala> result1.toRightIor("error!")
@@ -199,7 +220,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.Ior
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: Option[String] = Some("error!")
* scala> result1.toLeftIor(3)
@@ -220,7 +241,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.EitherNel
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: Option[Int] = Some(3)
* scala> result1.toRightNel("error!")
@@ -241,7 +262,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.EitherNec
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: Option[Int] = Some(3)
* scala> result1.toRightNec("error!")
@@ -263,7 +284,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.EitherNel
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val error1: Option[String] = Some("error!")
* scala> error1.toLeftNel(3)
@@ -286,7 +307,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.EitherNec
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val error1: Option[String] = Some("error!")
* scala> error1.toLeftNec(3)
@@ -306,7 +327,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val someString: Option[String] = Some("hello")
* scala> someString.orEmpty
@@ -324,7 +345,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> Some(1).liftTo[Either[CharSequence, *]]("Empty")
* res0: scala.Either[CharSequence, Int] = Right(1)
*
@@ -341,7 +362,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
*
* Example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> type F[A] = Either[String, A]
*
@@ -359,7 +380,7 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
* Transform the `Option` into a [[cats.data.OptionT]] while lifting it into the specified Applicative.
*
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val op: Option[Int] = Some(3)
* scala> op.toOptionT[List]
* res0: cats.data.OptionT[List, Int] = OptionT(List(Some(3)))
@@ -369,8 +390,8 @@ final class OptionOps[A](private val oa: Option[A]) extends AnyVal {
}
object OptionOps {
- final private[syntax] class LiftToPartiallyApplied[F[_], A](oa: Option[A]) {
- def apply[E](ifEmpty: => E)(implicit F: ApplicativeError[F, _ >: E]): F[A] =
+ final class LiftToPartiallyApplied[F[_], A](oa: Option[A]) {
+ def apply[E](ifEmpty: => E)(implicit F: ApplicativeError[F, ? >: E]): F[A] =
ApplicativeError.liftFromOption(oa, ifEmpty)
}
}
diff --git a/core/src/main/scala/cats/syntax/order.scala b/core/src/main/scala/cats/syntax/order.scala
index f49ab378c3..e96110de68 100644
--- a/core/src/main/scala/cats/syntax/order.scala
+++ b/core/src/main/scala/cats/syntax/order.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/package.scala b/core/src/main/scala/cats/syntax/package.scala
index cecf597b69..46b743455f 100644
--- a/core/src/main/scala/cats/syntax/package.scala
+++ b/core/src/main/scala/cats/syntax/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package object syntax {
diff --git a/core/src/main/scala/cats/syntax/parallel.scala b/core/src/main/scala/cats/syntax/parallel.scala
index 521a8826bd..f59fae17a8 100644
--- a/core/src/main/scala/cats/syntax/parallel.scala
+++ b/core/src/main/scala/cats/syntax/parallel.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.syntax
import cats.{
@@ -32,13 +53,24 @@ trait ParallelSyntax extends TupleParallelSyntax {
implicit final def catsSyntaxParallelSequence1[T[_]: Traverse, M[_], A](tma: T[M[A]]): ParallelSequenceOps1[T, M, A] =
new ParallelSequenceOps1(tma)
- implicit final def catsSyntaxParallelAp[M[_]: FlatMap, A](ma: M[A]): ParallelApOps[M, A] =
+ @deprecated("Kept for binary compatibility", "2.8.0")
+ final def catsSyntaxParallelAp[M[_]: FlatMap, A](ma: M[A]): ParallelApOps[M, A] =
new ParallelApOps(ma)
+
+ implicit final def catsSyntaxParallelAp1[M[_], A](ma: M[A]): ParallelApOps1[M, A] =
+ new ParallelApOps1(ma)
+
+ implicit final def catsSyntaxNonEmptyParallelAp[M[_], A](ma: M[A]): NonEmptyParallelApOps[M, A] =
+ new NonEmptyParallelApOps(ma)
}
trait ParallelApplySyntax {
- implicit final def catsSyntaxParallelApply[F[_], A, B](fa: F[A => B]): ParallelApplyOps[F, A, B] =
+ @deprecated("Kept for binary compatibility", "2.8.0")
+ final def catsSyntaxParallelApply[F[_], A, B](fa: F[A => B]): ParallelApplyOps[F, A, B] =
new ParallelApplyOps(fa)
+
+ implicit final def catsSyntaxNonEmptyParallelApply[F[_], A, B](fa: F[A => B]): NonEmptyParallelApplyOps[F, A, B] =
+ new NonEmptyParallelApplyOps(fa)
}
trait ParallelFlatSyntax {
@@ -76,9 +108,13 @@ trait ParallelTraverseFilterSyntax {
}
trait ParallelTraverseSyntax {
+ // Note: this could be renamed to `catsSyntaxParallelTraverseVoid` for consistency,
+ // but it looks like too much of a hassle of fighting binary compatibility issues for the implicit part of the API.
implicit final def catsSyntaxParallelTraverse_[T[_]: Foldable, A](ta: T[A]): ParallelTraversable_Ops[T, A] =
new ParallelTraversable_Ops(ta)
+ // Note: this could be renamed to `catsSyntaxParallelSequenceVoid` for consistency,
+ // but it looks like too much of a hassle of fighting binary compatibility issues for the implicit part of the API.
implicit final def catsSyntaxParallelSequence_[T[_]: Foldable, M[_], A](tma: T[M[A]]): ParallelSequence_Ops[T, M, A] =
new ParallelSequence_Ops(tma)
}
@@ -156,9 +192,13 @@ final class ParallelSequenceFilterOps[T[_], M[_], A](private val tmoa: T[M[Optio
Parallel.parSequenceFilter(tmoa)
}
+// Note: this could be renamed to `ParallelTraversableVoidOps` for consistency,
+// but it looks like too much of a hassle of fighting binary compatibility issues for the implicit part of the API.
final class ParallelTraversable_Ops[T[_], A](private val ta: T[A]) extends AnyVal {
+ def parTraverseVoid[M[_], B](f: A => M[B])(implicit T: Foldable[T], P: Parallel[M]): M[Unit] =
+ Parallel.parTraverseVoid(ta)(f)
def parTraverse_[M[_], B](f: A => M[B])(implicit T: Foldable[T], P: Parallel[M]): M[Unit] =
- Parallel.parTraverse_(ta)(f)
+ parTraverseVoid(f)
}
@deprecated("Kept for binary compatibility", "2.6.0")
@@ -185,9 +225,13 @@ final class ParallelSequenceOps1[T[_], M[_], A](private val tma: T[M[A]]) extend
Parallel.parSequence(tma)
}
+// Note: this could be renamed to `ParallelSequenceVoidOps` for consistency,
+// but it looks like too much of a hassle of fighting binary compatibility issues for the implicit part of the API.
final class ParallelSequence_Ops[T[_], M[_], A](private val tma: T[M[A]]) extends AnyVal {
+ def parSequenceVoid(implicit T: Foldable[T], P: Parallel[M]): M[Unit] =
+ Parallel.parSequenceVoid(tma)
def parSequence_(implicit T: Foldable[T], P: Parallel[M]): M[Unit] =
- Parallel.parSequence_(tma)
+ parSequenceVoid
}
@deprecated("Kept for binary compatibility", "2.6.0")
@@ -237,8 +281,8 @@ final class ParallelUnorderedFlatSequenceOps[T[_], M[_], A](private val tmta: T[
Parallel.parUnorderedFlatSequence(tmta)
}
+@deprecated("Kept for binary compatibility", "2.8.0")
final class ParallelApOps[M[_], A](private val ma: M[A]) extends AnyVal {
-
def &>[B](mb: M[B])(implicit P: Parallel[M]): M[B] =
P.parProductR(ma)(mb)
@@ -256,8 +300,36 @@ final class ParallelApOps[M[_], A](private val ma: M[A]) extends AnyVal {
def parReplicateA(n: Int)(implicit P: Parallel[M]): M[List[A]] =
Parallel.parReplicateA(n, ma)
+
+ def parReplicateA_(n: Int)(implicit P: Parallel[M]): M[Unit] =
+ Parallel.parReplicateA_(n, ma)
+}
+
+final class ParallelApOps1[M[_], A](private val ma: M[A]) extends AnyVal {
+ def parReplicateA(n: Int)(implicit P: Parallel[M]): M[List[A]] =
+ Parallel.parReplicateA(n, ma)
+ def parReplicateA_(n: Int)(implicit P: Parallel[M]): M[Unit] =
+ Parallel.parReplicateA_(n, ma)
}
+final class NonEmptyParallelApOps[M[_], A](private val ma: M[A]) extends AnyVal {
+ def &>[B](mb: M[B])(implicit P: NonEmptyParallel[M]): M[B] =
+ P.parProductR[A, B](ma)(mb)
+
+ def <&[B](mb: M[B])(implicit P: NonEmptyParallel[M]): M[A] =
+ P.parProductL[A, B](ma)(mb)
+
+ def parProductL[B](mb: M[B])(implicit P: NonEmptyParallel[M]): M[A] =
+ P.parProductL[A, B](ma)(mb)
+
+ def parProductR[B](mb: M[B])(implicit P: NonEmptyParallel[M]): M[B] =
+ P.parProductR[A, B](ma)(mb)
+
+ def parProduct[B](mb: M[B])(implicit P: NonEmptyParallel[M]): M[(A, B)] =
+ Parallel.parProduct(ma, mb)
+}
+
+@deprecated("Kept for binary compatibility", "2.8.0")
final class ParallelApplyOps[M[_], A, B](private val mab: M[A => B]) extends AnyVal {
def <&>(ma: M[A])(implicit P: Parallel[M]): M[B] =
Parallel.parAp(mab)(ma)(P)
@@ -266,6 +338,14 @@ final class ParallelApplyOps[M[_], A, B](private val mab: M[A => B]) extends Any
Parallel.parAp(mab)(ma)
}
+final class NonEmptyParallelApplyOps[M[_], A, B](private val mab: M[A => B]) extends AnyVal {
+ def <&>(ma: M[A])(implicit P: NonEmptyParallel[M]): M[B] =
+ Parallel.parAp[M, A, B](mab)(ma)(P)
+
+ def parAp(ma: M[A])(implicit P: NonEmptyParallel[M]): M[B] =
+ Parallel.parAp[M, A, B](mab)(ma)
+}
+
final class ParallelBitraverseOps[T[_, _], A, B](private val tab: T[A, B]) extends AnyVal {
def parBitraverse[M[_], C, D](f: A => M[C], g: B => M[D])(implicit T: Bitraverse[T], P: Parallel[M]): M[T[C, D]] =
Parallel.parBitraverse(tab)(f, g)
diff --git a/core/src/main/scala/cats/syntax/partialOrder.scala b/core/src/main/scala/cats/syntax/partialOrder.scala
index e4476c6296..45cbb8ca1e 100644
--- a/core/src/main/scala/cats/syntax/partialOrder.scala
+++ b/core/src/main/scala/cats/syntax/partialOrder.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/profunctor.scala b/core/src/main/scala/cats/syntax/profunctor.scala
index 3bc780f11d..75edd22b0b 100644
--- a/core/src/main/scala/cats/syntax/profunctor.scala
+++ b/core/src/main/scala/cats/syntax/profunctor.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/reducible.scala b/core/src/main/scala/cats/syntax/reducible.scala
index 415a723ee5..1e07ad776e 100644
--- a/core/src/main/scala/cats/syntax/reducible.scala
+++ b/core/src/main/scala/cats/syntax/reducible.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/representable.scala b/core/src/main/scala/cats/syntax/representable.scala
index 9920cb410b..486b94fb5f 100644
--- a/core/src/main/scala/cats/syntax/representable.scala
+++ b/core/src/main/scala/cats/syntax/representable.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/semigroup.scala b/core/src/main/scala/cats/syntax/semigroup.scala
index 7afd259086..ac4cec95d7 100644
--- a/core/src/main/scala/cats/syntax/semigroup.scala
+++ b/core/src/main/scala/cats/syntax/semigroup.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
trait SemigroupSyntax {
- // TODO: use simulacrum instances eventually
+
implicit final def catsSyntaxSemigroup[A: Semigroup](a: A): SemigroupOps[A] =
new SemigroupOps[A](a)
}
diff --git a/core/src/main/scala/cats/syntax/semigroupal.scala b/core/src/main/scala/cats/syntax/semigroupal.scala
index 13786bb911..e80bd78fd1 100644
--- a/core/src/main/scala/cats/syntax/semigroupal.scala
+++ b/core/src/main/scala/cats/syntax/semigroupal.scala
@@ -1,14 +1,74 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
trait SemigroupalSyntax {
- implicit final def catsSyntaxSemigroupal[F[_], A](fa: F[A])(implicit F: Semigroupal[F]): SemigroupalOps[F, A] =
+ @deprecated("Use `catsSyntaxSemigroupalOps2`", "2.10.0")
+ final def catsSyntaxSemigroupal[F[_], A](fa: F[A], F: Semigroupal[F]): SemigroupalOps[F, A] =
new SemigroupalOps[F, A] {
type TypeClassType = Semigroupal[F]
val self = fa
val typeClassInstance = F
}
+
+ implicit def catsSyntaxSemigroupalOps2[F[_], A](fa: F[A]): SemigroupalOps2[F, A] =
+ new SemigroupalOps2[F, A](fa)
+
+}
+
+final class SemigroupalOps2[F[_], A](private val fa: F[A]) extends AnyVal {
+
+ /**
+ * @see [[Semigroupal.product]]
+ *
+ * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ *
+ * scala> val noneInt: Option[Int] = None
+ * scala> val some3: Option[Int] = Some(3)
+ * scala> val noneString: Option[String] = None
+ * scala> val someFoo: Option[String] = Some("foo")
+ *
+ * scala> noneInt.product(noneString)
+ * res0: Option[(Int, String)] = None
+ *
+ * scala> noneInt.product(someFoo)
+ * res1: Option[(Int, String)] = None
+ *
+ * scala> some3.product(noneString)
+ * res2: Option[(Int, String)] = None
+ *
+ * scala> some3.product(someFoo)
+ * res3: Option[(Int, String)] = Some((3,foo))
+ * }}}
+ */
+ def product[B](fb: F[B])(implicit F: Semigroupal[F]): F[(A, B)] = F.product(fa, fb)
+
+ @deprecated("Replaced by an apply syntax, e.g. instead of (a |@| b).map(...) use (a, b).mapN(...)", "1.0.0-MF")
+ def |@|[B](fb: F[B]): SemigroupalBuilder[F]#SemigroupalBuilder2[A, B] =
+ new SemigroupalBuilder[F] |@| fa |@| fb
}
abstract class SemigroupalOps[F[_], A] extends Semigroupal.Ops[F, A] {
diff --git a/core/src/main/scala/cats/syntax/semigroupk.scala b/core/src/main/scala/cats/syntax/semigroupk.scala
index 832501764a..696bbeb3e5 100644
--- a/core/src/main/scala/cats/syntax/semigroupk.scala
+++ b/core/src/main/scala/cats/syntax/semigroupk.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/seq.scala b/core/src/main/scala/cats/syntax/seq.scala
index e3601232c4..ef08518316 100644
--- a/core/src/main/scala/cats/syntax/seq.scala
+++ b/core/src/main/scala/cats/syntax/seq.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.syntax
import cats.data.NonEmptySeq
diff --git a/core/src/main/scala/cats/syntax/set.scala b/core/src/main/scala/cats/syntax/set.scala
index 2977d5f880..fa7d58a31b 100644
--- a/core/src/main/scala/cats/syntax/set.scala
+++ b/core/src/main/scala/cats/syntax/set.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.syntax
import scala.collection.immutable.{SortedMap, SortedSet}
@@ -17,7 +38,7 @@ final class SetOps[A](private val se: SortedSet[A]) extends AnyVal {
* {{{
* scala> import scala.collection.immutable.SortedSet
* scala> import cats.data.NonEmptySet
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: SortedSet[Int] = SortedSet(1, 2)
* scala> result1.toNes
@@ -37,7 +58,7 @@ final class SetOps[A](private val se: SortedSet[A]) extends AnyVal {
* {{{
* scala> import cats.data.NonEmptySet
* scala> import scala.collection.immutable.{SortedMap, SortedSet}
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val sortedSet = SortedSet(12, -2, 3, -5)
*
diff --git a/core/src/main/scala/cats/syntax/show.scala b/core/src/main/scala/cats/syntax/show.scala
index 45e94fe15d..85ffe0f11c 100644
--- a/core/src/main/scala/cats/syntax/show.scala
+++ b/core/src/main/scala/cats/syntax/show.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/strong.scala b/core/src/main/scala/cats/syntax/strong.scala
index 602d38334e..fd4f0fc02c 100644
--- a/core/src/main/scala/cats/syntax/strong.scala
+++ b/core/src/main/scala/cats/syntax/strong.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/traverse.scala b/core/src/main/scala/cats/syntax/traverse.scala
index 9205507f3b..f7bb69f5e3 100644
--- a/core/src/main/scala/cats/syntax/traverse.scala
+++ b/core/src/main/scala/cats/syntax/traverse.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/traverseFilter.scala b/core/src/main/scala/cats/syntax/traverseFilter.scala
index c3ff4b95c4..65f0e43ddb 100644
--- a/core/src/main/scala/cats/syntax/traverseFilter.scala
+++ b/core/src/main/scala/cats/syntax/traverseFilter.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -6,13 +27,16 @@ trait TraverseFilterSyntax extends TraverseFilter.ToTraverseFilterOps
private[syntax] trait TraverseFilterSyntaxBinCompat0 {
implicit def toSequenceFilterOps[F[_], G[_], A](fgoa: F[G[Option[A]]]): SequenceFilterOps[F, G, A] =
new SequenceFilterOps(fgoa)
+
+ implicit def toTraverseFilterOps[F[_], G[_], A](fa: F[A]): TraverseFilterOps[F, G, A] =
+ new TraverseFilterOps(fa)
}
final class SequenceFilterOps[F[_], G[_], A](private val fgoa: F[G[Option[A]]]) extends AnyVal {
/**
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val a: List[Either[String, Option[Int]]] = List(Right(Some(1)), Right(Some(5)), Right(Some(3)))
* scala> val b: Either[String, List[Int]] = a.sequenceFilter
* b: Either[String, List[Int]] = Right(List(1, 5, 3))
@@ -20,3 +44,12 @@ final class SequenceFilterOps[F[_], G[_], A](private val fgoa: F[G[Option[A]]])
*/
def sequenceFilter(implicit F: TraverseFilter[F], G: Applicative[G]): G[F[A]] = F.sequenceFilter(fgoa)
}
+
+final class TraverseFilterOps[F[_], G[_], A](private val fa: F[A]) extends AnyVal {
+
+ def traverseCollect[B](f: PartialFunction[A, G[B]])(implicit
+ F: TraverseFilter[F],
+ G: Applicative[G]
+ ): G[F[B]] =
+ F.traverseCollect(fa)(f)
+}
diff --git a/core/src/main/scala/cats/syntax/unorderedFoldable.scala b/core/src/main/scala/cats/syntax/unorderedFoldable.scala
index 99f2ee1a3f..2a793c2552 100644
--- a/core/src/main/scala/cats/syntax/unorderedFoldable.scala
+++ b/core/src/main/scala/cats/syntax/unorderedFoldable.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -8,12 +29,30 @@ trait UnorderedFoldableSyntax extends UnorderedFoldable.ToUnorderedFoldableOps {
final class UnorderedFoldableOps[F[_], A](private val fa: F[A]) extends AnyVal {
+ /**
+ * Tests if this `F[A]` contains `v` using the `Eq` instance for `A`,
+ * named contains_ to avoid conflict with existing contains which uses universal equality.
+ *
+ * Example:
+ * {{{
+ * scala> import cats.syntax.all._
+ *
+ * scala> val l: List[Int] = List(1, 2, 3, 4)
+ * scala> l.contains_(1)
+ * res0: Boolean = true
+ * scala> l.contains_(5)
+ * res1: Boolean = false
+ * }}}
+ */
+ def contains_(v: A)(implicit ev: Eq[A], F: UnorderedFoldable[F]): Boolean =
+ F.contains_(fa, v)
+
/**
* Count the number of elements in the structure that satisfy the given predicate.
*
* For example:
* {{{
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
* scala> val map1 = Map[Int, String]()
* scala> val p1: String => Boolean = _.length > 0
* scala> map1.count(p1)
diff --git a/core/src/main/scala/cats/syntax/unorderedTraverse.scala b/core/src/main/scala/cats/syntax/unorderedTraverse.scala
index 5d9349b790..382d3ac880 100644
--- a/core/src/main/scala/cats/syntax/unorderedTraverse.scala
+++ b/core/src/main/scala/cats/syntax/unorderedTraverse.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/core/src/main/scala/cats/syntax/validated.scala b/core/src/main/scala/cats/syntax/validated.scala
index 758818a36f..68cc1bdda9 100644
--- a/core/src/main/scala/cats/syntax/validated.scala
+++ b/core/src/main/scala/cats/syntax/validated.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
@@ -20,7 +41,7 @@ trait ValidatedExtensionSyntax {
}
final class ValidatedExtension[E, A](private val self: Validated[E, A]) extends AnyVal {
- def liftTo[F[_]](implicit F: ApplicativeError[F, _ >: E]): F[A] =
+ def liftTo[F[_]](implicit F: ApplicativeError[F, ? >: E]): F[A] =
F.fromValidated(self)
}
@@ -36,7 +57,7 @@ final private[syntax] class ValidatedIdOpsBinCompat0[A](private val a: A) extend
*
* For example:
* {{{
- * scala> import cats.implicits._, cats.data._
+ * scala> import cats.syntax.all._, cats.data._
* scala> 1.validNec[String]
* res0: Validated[NonEmptyChain[String], Int] = Valid(1)
* }}}
@@ -48,7 +69,7 @@ final private[syntax] class ValidatedIdOpsBinCompat0[A](private val a: A) extend
*
* For example:
* {{{
- * scala> import cats.implicits._, cats.data._
+ * scala> import cats.syntax.all._, cats.data._
* scala> "Err".invalidNec[Int]
* res0: Validated[NonEmptyChain[String], Int] = Invalid(Chain(Err))
* }}}
diff --git a/core/src/main/scala/cats/syntax/vector.scala b/core/src/main/scala/cats/syntax/vector.scala
index 9185f29927..d32967a80b 100644
--- a/core/src/main/scala/cats/syntax/vector.scala
+++ b/core/src/main/scala/cats/syntax/vector.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.syntax
import cats.data.NonEmptyVector
@@ -17,7 +38,7 @@ final class VectorOps[A](private val va: Vector[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.NonEmptyVector
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: Vector[Int] = Vector(1, 2)
* scala> result1.toNev
@@ -37,7 +58,7 @@ final class VectorOps[A](private val va: Vector[A]) extends AnyVal {
* {{{
* scala> import cats.data.NonEmptyVector
* scala> import scala.collection.immutable.SortedMap
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val vector = Vector(12, -2, 3, -5)
*
@@ -59,7 +80,7 @@ final class VectorOps[A](private val va: Vector[A]) extends AnyVal {
* {{{
* scala> import cats.data.NonEmptyVector
* scala> import scala.collection.immutable.SortedMap
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val vector = Vector(12, -2, 3, -5)
*
@@ -90,7 +111,7 @@ final class VectorOps[A](private val va: Vector[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.NonEmptyVector
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: Vector[Int] = Vector(1, 2)
* scala> result1.scanLeftNev(100)(_ + _)
@@ -111,7 +132,7 @@ final class VectorOps[A](private val va: Vector[A]) extends AnyVal {
* Example:
* {{{
* scala> import cats.data.NonEmptyVector
- * scala> import cats.implicits._
+ * scala> import cats.syntax.all._
*
* scala> val result1: Vector[Int] = Vector(1, 2)
* scala> result1.scanRightNev(100)(_ + _)
diff --git a/core/src/main/scala/cats/syntax/writer.scala b/core/src/main/scala/cats/syntax/writer.scala
index 1f7b055ff8..e6ad28a4c9 100644
--- a/core/src/main/scala/cats/syntax/writer.scala
+++ b/core/src/main/scala/cats/syntax/writer.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package syntax
diff --git a/docs/ADOPTERS.md b/docs/ADOPTERS.md
new file mode 120000
index 0000000000..39390f1593
--- /dev/null
+++ b/docs/ADOPTERS.md
@@ -0,0 +1 @@
+../ADOPTERS.md
\ No newline at end of file
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
new file mode 120000
index 0000000000..44fcc63439
--- /dev/null
+++ b/docs/CONTRIBUTING.md
@@ -0,0 +1 @@
+../CONTRIBUTING.md
\ No newline at end of file
diff --git a/docs/src/main/mdoc/algebra.md b/docs/algebra.md
similarity index 95%
rename from docs/src/main/mdoc/algebra.md
rename to docs/algebra.md
index 9607cc7685..7e4972284e 100644
--- a/docs/src/main/mdoc/algebra.md
+++ b/docs/algebra.md
@@ -1,8 +1,4 @@
----
-layout: docs
-title: "Algebra Overview"
-section: "algebra"
----
+{% laika.title = Algebra %}
# Algebra Overview
@@ -59,9 +55,10 @@ All ring-like structures are associative for both `+` and `*`, have commutative
|CommutativeRig | | ✓| | ✓|
|Ring | ✓| ✓| | |
|CommutativeRing | ✓| ✓| | ✓|
+|Semifield | | ✓| ✓| |
+|CommutativeSemifield| | ✓| ✓| ✓|
|Field | ✓| ✓| ✓| ✓|
-With the exception of `CommutativeRig` and `Rng`, every lower structure is also an instance of the structures above it. For example, every `Ring` is a `Rig`, every `Field` is a `CommutativeRing`, and so on.
(For a description of what the terminology in each column means, see [§algebraic properties and terminology](#algebraic-properties-and-terminology).)
@@ -110,4 +107,4 @@ Also, a `Bool` gives rise to a `BoolRing`, since each element can be defined as
### Documentation Help
-We'd love your help with this documentation! You can edit this page in your browser by clicking [this link](https://github.com/typelevel/cats/edit/master/docs/src/main/mdoc/algebra.md).
+We'd love your help with this documentation! You can edit this page in your browser by clicking [this link](https://github.com/typelevel/cats/edit/main/docs/algebra.md).
diff --git a/alleycats-core/README.md b/docs/alleycats.md
similarity index 93%
rename from alleycats-core/README.md
rename to docs/alleycats.md
index 2eaaa48297..111d670c2c 100644
--- a/alleycats-core/README.md
+++ b/docs/alleycats.md
@@ -1,6 +1,6 @@
-## Alleycats
+# Alleycats
-### Overview
+## Overview
Alleycats is a module of the [Cats](https://github.com/typelevel/cats)
project that exists to support types which are not entirely savory or
@@ -16,12 +16,12 @@ some notion of "emptiness").
Rather than argue about whether to permit these types in Cats proper, we
provide a (slightly disreputable) home for them here.
-### Type classes
+## Type classes
Alleycats introduces several new type classes. Here is an overview of
the instances introduced.
-#### Empty[A], Zero[A], and One[A]
+### Empty\[A\], Zero\[A\], and One\[A\]
A commonly-requested type class is one that encodes the idea of a set
having an identity element. Normally this would be done by defining a
@@ -49,7 +49,7 @@ effect).
The same rules apply to `Zero[A]` and `One[A]` and their respective
associative operations.
-#### Pure[F[\_]] and Extract[F[\_]]
+### Pure\[F\[\_\]\] and Extract\[F\[\_\]\]
The `Pure[F]` type class represents the `pure` method of
`Applicative[F]` separated from its `map` and `ap` methods. Like the
@@ -62,18 +62,18 @@ Similarly, `Extract[F]` represents the `extract` method of
and `CoflatMap[F]` are available, they should provide a valid
`Comonad[F]` instance.
-#### EmptyK[F[\_]]
+### EmptyK\[F\[\_\]\]
Finally, `EmptyK[F]` generalizes the `empty[A]` method from
`MonoidK[F]`. The pattern here is the same as before --
`SemigroupK[F]` and `EmptyK[F]` should provide a valid `MonoidK[F]`
instance.
-### Instances
+## Instances
Alleycats also provides some "disreputable" type class instances.
-#### Set[\_] instances
+### Set\[\_\] instances
Scala's `Set[_]` takes advantage of the universal availability of
`.hashCode` and `.equals`. This makes it difficult to use
@@ -84,7 +84,7 @@ and monads.
Alleycats provides `Monad[Set]` and `Traverse[Set]`. You can import
these instances via `import alleycats.std.set._`.
-#### Try[\_] instances
+### Try\[\_\] instances
Scala's `Try[_]` is intended to replace the need for `try { ... }
catch { ... }` syntax in Scala programs, to ease error-handling, and
@@ -95,7 +95,7 @@ that `Try` fulfills the necessary functor/monad laws.
Alleycats provides a `Monad[Try]`. You can import this instance via
`import alleycats.std.try._`.
-#### Iterable[\_] instances
+### Iterable\[\_\] instances
Scala's `collection.Iterable[_]` offers no guarantees that it's immutable,
since it abstracts over the `mutable` and `immutable` variants. However it's
@@ -103,14 +103,14 @@ the type used to represent a `Map`s `values`, and its often desirable to treat t
values of a map as a `Foldable` collection. Alleycats provides a `Foldable[Iterable]`, eg:
```
-import cats.implicits._
+import cats.syntax.all._
import alleycats.std.iterable._
// Result "AppleOrange"
Map(1 -> "Apple", 2 -> "Orange").values.combineAll
```
-### Contributing
+## Contributing
This module's goal is to be very liberal about accepting type class
instances, but to only provide instances which are absent from
diff --git a/docs/src/main/mdoc/colophon.md b/docs/colophon.md
similarity index 75%
rename from docs/src/main/mdoc/colophon.md
rename to docs/colophon.md
index 851cd38c72..5b41227fb5 100644
--- a/docs/src/main/mdoc/colophon.md
+++ b/docs/colophon.md
@@ -1,9 +1,5 @@
----
-layout: page
-title: "Colophon"
-section: "colophon"
-position: 60
----
+# Colophon
+
Cats has been made a much better project, and is a much more enjoyable
project to work on because of many of the other projects on which Cats
is built. Many of these projects have had enhancements made in order
@@ -13,11 +9,10 @@ We would like to thank the maintainers of these supporting projects,
and we'd encourage you to check out these projects and consider
integrating them into your own projects.
- * [simulacrum](https://github.com/typelevel/simulacrum) for minimizing type class boilerplate
* [scalacheck](http://scalacheck.org) for property-based testing
* [discipline](https://github.com/typelevel/discipline) for encoding and testing laws
* [kind-projector](https://github.com/typelevel/kind-projector) for type lambda syntax
- * [tut](https://github.com/tpolecat/tut) type-checked example code makes sure that our examples stay in sync with the rest of our source
+ * [mdoc](https://github.com/scalameta/mdoc) type-checked example code makes sure that our examples stay in sync with the rest of our source
There are other libraries that aim to foster Functional Programming in the Scala programming language which Cats has a relationship to:
@@ -26,4 +21,4 @@ There are other libraries that aim to foster Functional Programming in the Scala
nature to Cats, also derived from scalaz. The Structures and Cats
projects have had a healthy relationship of sharing both ideas and code.
-For a full list of Cats and Typelevel related projects and libraries, take a look at [The Typelevel Ecosystem](https://typelevel.org/cats/typelevelEcosystem.html)
+For a full list of Cats and Typelevel related projects and libraries, take a look at [The Typelevel Ecosystem](typelevelEcosystem.md)
diff --git a/docs/datatypes.md b/docs/datatypes.md
new file mode 100644
index 0000000000..b151b8ebe5
--- /dev/null
+++ b/docs/datatypes.md
@@ -0,0 +1,5 @@
+{% laika.title = "Data Types" %}
+
+@:navigationTree {
+ entries = [ { target = "datatypes", depth = 2 } ]
+}
diff --git a/docs/datatypes/chain.md b/docs/datatypes/chain.md
new file mode 100644
index 0000000000..01029259c5
--- /dev/null
+++ b/docs/datatypes/chain.md
@@ -0,0 +1,182 @@
+# Chain
+
+API Documentation: @:api(cats.data.Chain)
+
+`Chain` is an immutable sequence data structure that allows constant time prepending, appending and concatenation.
+This makes it especially efficient when used as a [Monoid], e.g. with [Validated] or [Writer].
+As such it aims to be used where @:api(scala.collection.immutable.List) and @:api(scala.collection.immutable.Vector) incur a performance penalty.
+Cats also includes type class implementations to support using `Chain` as a general-purpose collection type, including [Traverse], [Monad], and [Alternative].
+
+## Motivation
+
+`List` is a great data type, it is very simple and easy to understand.
+It has very low overhead for the most important functions such as [fold][Foldable] and [map][Functor] and also supports prepending a single element in constant time.
+
+Traversing a data structure with something like [Writer\[List\[Log\], A\]][Writer] or [ValidatedNel\[Error, A\]][Validated] is powerful and allows us to precisely specify what kind of iteration we want to do while remaining succinct.
+However, in terms of efficiency it's a whole different story unfortunately.
+That is because both of these traversals make use of the `List` monoid (or the [NonEmptyList] semigroup), which by the nature of `List` is very inefficient.
+If you use [traverse][Traverse] with a data structure with `n` elements and [Writer] or [Validated] as the [Applicative] type, you will end up with a runtime of `O(n^2)`.
+This is because, with `List`, appending a single element requires iterating over the entire data structure and therefore takes linear time.
+
+So @:api(scala.collection.immutable.List) isn't all that great for this use case, so let's use @:api(scala.collection.immutable.Vector) or @:api(cats.data.NonEmptyVector)` instead, right?
+
+Well, `Vector` has its own problems and in this case it's unfortunately not that much faster than `List` at all. You can check [this blog post](http://www.lihaoyi.com/post/BenchmarkingScalaCollections.html#vectors-are-ok) by Li Haoyi for some deeper insight into `Vector`'s issues.
+
+
+`Chain` evolved from what used to be `fs2.Catenable` and Erik Osheim's [Chain](https://github.com/non/chain) library.
+Similar to `List`, it is also a very simple data structure, but unlike `List` it supports constant O(1) time `append`, `prepend` and `concat`.
+This makes its [Monoid] instance [super performant][Benchmarks] and a much better fit for usage with [Validated], [Writer], [Ior] or [Const].
+
+
+## NonEmptyChain
+
+[NonEmptyChain][nec] is the non-empty version of `Chain`.
+It does not have a [Monoid] instance since it cannot be empty, but it does have a [Semigroup] instance.
+Likewise, it defines a [NonEmptyTraverse] instance, but no @:api(cats.TraverseFilter) instance.
+
+To simplify the usage of `NonEmptyChain`, Cats includes type aliases like [ValidatedNec](validated.md#meeting-applicative) and [IorNec](ior.md#using-with-nonemptychain), as well as helper functions like `groupByNec` and `Validated.invalidNec`.
+
+There are numerous ways to construct a `NonEmptyChain`, e.g. you can create one from a single element, a `NonEmptyList` or a `NonEmptyVector`:
+
+```scala mdoc
+import cats.data._
+
+NonEmptyChain(1, 2, 3, 4)
+
+NonEmptyChain.fromNonEmptyList(NonEmptyList(1, List(2, 3)))
+NonEmptyChain.fromNonEmptyVector(NonEmptyVector(1, Vector(2, 3)))
+
+NonEmptyChain.one(1)
+```
+
+
+
+You can also create an @:api(scala.Option) of `NonEmptyChain` from a `Chain` or any other collection type:
+
+```scala mdoc
+import cats.data._
+
+NonEmptyChain.fromChain(Chain(1, 2, 3))
+NonEmptyChain.fromSeq(List.empty[Int])
+NonEmptyChain.fromSeq(Vector(1, 2, 3))
+```
+
+Sometimes, you'll want to prepend or append a single element to a chain and return the result as a `NonEmptyChain`:
+
+```scala mdoc
+import cats.data._
+
+NonEmptyChain.fromChainAppend(Chain(1, 2, 3), 4)
+NonEmptyChain.fromChainAppend(Chain.empty[Int], 1)
+NonEmptyChain.fromChainPrepend(1, Chain(2, 3))
+```
+## How it works
+
+`Chain` is implemented as a simple unbalanced binary tree ADT with four cases:
+an empty `Chain` with no elements, a singleton `Chain` with exactly one element, a concatenation of two chains, or a wrapper for a @:api(scala.collection.immutable.Seq).
+
+In code it looks like this:
+
+```scala mdoc
+sealed abstract class Chain[+A]
+
+case object Empty extends Chain[Nothing]
+case class Singleton[A](a: A) extends Chain[A]
+case class Append[A](left: Chain[A], right: Chain[A]) extends Chain[A]
+case class Wrap[A](seq: Seq[A]) extends Chain[A]
+```
+
+The `Append` constructor is what gives us the fast concatenation ability.
+Concatenating two existing `Chain`s is just a call to the `Append` constructor, which is always constant time `O(1)`.
+
+In case we want to append or prepend a single element,
+ all we have to do is wrap the element with the `Singleton` constructor and then use the `Append` constructor to append or prepend the `Singleton` `Chain`.
+
+The `Wrap` constructor lifts any `Seq` into a `Chain`.
+This can be useful for concatenating already created collections that don't have great concatenation performance.
+`Append(Wrap(list1), Wrap(list2)).foldMap(f)` will in general be much faster than just concatenating `list1` and `list2` and folding the result.
+
+`Chain` doesn't directly expose the `Append` and `Wrap` constructors, because the arguments might refer to an empty `Chain` or `Seq`.
+Instead of calling `Append` directly you can simply use `Chain.concat` or `++`, which will check if one of the arguments is empty:
+
+```scala
+def concat[A](c: Chain[A], c2: Chain[A]): Chain[A] =
+ if (c.isEmpty) c2
+ else if (c2.isEmpty) c
+ else Append(c, c2)
+```
+
+To construct a `Chain` from a `Seq` you should use `Chain.fromSeq` which will also check for emptiness:
+
+```scala
+def fromSeq[A](s: Seq[A]): Chain[A] =
+ if (s.isEmpty) nil
+ else if (s.lengthCompare(1) == 0) one(s.head)
+ else Wrap(s)
+```
+
+In conclusion `Chain` supports constant time concatenation, because it builds an unbalance tree of `Append`s.
+`append` and `prepend` are treated as concatenation with single element collection to keep the same performance characteristics.
+This unbalanced tree will always allow iteration in linear time.
+
+## Benchmarks
+
+To get a good idea of performance of `Chain`, here are some benchmarks that test monoidal append (higher score is better):
+
+```
+Benchmark Mode Cnt Score Error Units
+CollectionMonoidBench.accumulateChain thrpt 25 81.973 ± 3.921 ops/s
+CollectionMonoidBench.accumulateList thrpt 25 21.150 ± 1.756 ops/s
+CollectionMonoidBench.accumulateVector thrpt 25 11.725 ± 0.306 ops/s
+```
+
+As you can see accumulating things with `Chain` is almost 4 times faster than `List` and nearly 8 times faster than `Vector`.
+So appending is a lot more performant than the standard library collections, but what about operations like `map` or `fold`?
+Fortunately we've also benchmarked these (again, higher score is better):
+
+```
+Benchmark Mode Cnt Score Error Units
+ChainBench.consLargeChain thrpt 25 143759156.264 ± 5611584.788 ops/s
+ChainBench.consLargeList thrpt 25 148512687.273 ± 5992793.489 ops/s
+ChainBench.consLargeVector thrpt 25 7249505.257 ± 202436.549 ops/s
+ChainBench.consSmallChain thrpt 25 119925876.637 ± 1663011.363 ops/s
+ChainBench.consSmallList thrpt 25 152664330.695 ± 1828399.646 ops/s
+ChainBench.consSmallVector thrpt 25 57686442.030 ± 533768.670 ops/s
+ChainBench.createChainOption thrpt 25 167191685.222 ± 1474976.197 ops/s
+ChainBench.createChainSeqOption thrpt 25 21264365.364 ± 372757.348 ops/s
+ChainBench.createSmallChain thrpt 25 87260308.052 ± 960407.889 ops/s
+ChainBench.createSmallList thrpt 25 20000981.857 ± 396001.340 ops/s
+ChainBench.createSmallVector thrpt 25 26311376.712 ± 288871.258 ops/s
+ChainBench.createTinyChain thrpt 25 75311482.869 ± 1066466.694 ops/s
+ChainBench.createTinyList thrpt 25 67502351.990 ± 1071560.419 ops/s
+ChainBench.createTinyVector thrpt 25 39676430.380 ± 405717.649 ops/s
+ChainBench.foldLeftLargeChain thrpt 25 117.866 ± 3.343 ops/s
+ChainBench.foldLeftLargeList thrpt 25 193.640 ± 2.298 ops/s
+ChainBench.foldLeftLargeVector thrpt 25 178.370 ± 0.830 ops/s
+ChainBench.foldLeftSmallChain thrpt 25 43732934.777 ± 362285.965 ops/s
+ChainBench.foldLeftSmallList thrpt 25 51155941.055 ± 882005.961 ops/s
+ChainBench.foldLeftSmallVector thrpt 25 41902918.940 ± 53030.742 ops/s
+ChainBench.lengthLargeChain thrpt 25 131831.918 ± 1613.341 ops/s
+ChainBench.lengthLargeList thrpt 25 271.015 ± 0.962 ops/s
+ChainBench.mapLargeChain thrpt 25 78.162 ± 2.620 ops/s
+ChainBench.mapLargeList thrpt 25 73.676 ± 8.999 ops/s
+ChainBench.mapLargeVector thrpt 25 132.443 ± 2.360 ops/s
+ChainBench.mapSmallChain thrpt 25 24047623.583 ± 1834073.508 ops/s
+ChainBench.mapSmallList thrpt 25 21482014.328 ± 387854.819 ops/s
+ChainBench.mapSmallVector thrpt 25 34707281.383 ± 382477.558 ops/s
+ChainBench.reverseLargeChain thrpt 25 37700.549 ± 154.942 ops/s
+ChainBench.reverseLargeList thrpt 25 142.832 ± 3.626 ops/s
+```
+
+While not dominant, `Chain` performance is in the middle of the pack for most operations benchmarked.
+`Chain` does have poor random access performance, and should be avoided in favor of `Vector` for random access heavy use cases.
+
+Chain excels with concatenation heavy workloads and has comparable performance to `List` and `Vector` for most other operations.
+So next time you write any code that uses `List` or `Vector` as a [Monoid], be sure to use `Chain` instead!
+
+> Note: All benchmarks above were run using JMH 1.32 with Scala 2.13.8 on JDK 11.
+For full details, see [here](https://github.com/typelevel/cats/pull/4264).
+You can also check out the [benchmark source code](https://github.com/typelevel/cats/blob/v@VERSION@/bench/src/main/scala/cats/bench).
+
+
+[nec]: @API_LINK_BASE@/cats/data/index.html#NonEmptyChain:cats.data.NonEmptyChainImpl.type
\ No newline at end of file
diff --git a/docs/src/main/mdoc/datatypes/const.md b/docs/datatypes/const.md
similarity index 98%
rename from docs/src/main/mdoc/datatypes/const.md
rename to docs/datatypes/const.md
index 181edd9d11..33792350e8 100644
--- a/docs/src/main/mdoc/datatypes/const.md
+++ b/docs/datatypes/const.md
@@ -1,11 +1,7 @@
----
-layout: docs
-title: "Const"
-section: "data"
-source: "core/src/main/scala/cats/data/Const.scala"
-scaladoc: "#cats.data.Const"
----
# Const
+
+API Documentation: @:api(cats.data.Const)
+
At first glance `Const` seems like a strange data type - it has two type parameters, yet only
stores a value of the first type. What possible use is it? As it turns out, it does
have its uses, which serve as a nice example of the consistency and elegance of functional programming.
@@ -80,7 +76,7 @@ only thing we need is a `map` operation on the data type. Being good functional
```scala mdoc:nest:silent
import cats.Functor
-import cats.implicits._
+import cats.syntax.all._
trait Lens[S, A] {
def get(s: S): A
diff --git a/docs/src/main/mdoc/datatypes/contt.md b/docs/datatypes/contt.md
similarity index 97%
rename from docs/src/main/mdoc/datatypes/contt.md
rename to docs/datatypes/contt.md
index 3253e8972b..503bd31f78 100644
--- a/docs/src/main/mdoc/datatypes/contt.md
+++ b/docs/datatypes/contt.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "ContT"
-section: "data"
-source: "core/src/main/scala/cats/data/ContT.scala"
-scaladoc: "#cats.data.ContT"
----
# ContT
+API Documentation: @:api(cats.data.ContT)
+
A pattern that appears sometimes in functional programming is that of a function
first computing some kind of intermediate result and then passing that result to
another function which was passed in as an argument, in order to delegate the
@@ -35,7 +30,7 @@ def updateUser(persistToDatabase: User => Eval[UserUpdateResult])
```
(Note: We will be using `Eval` throughout the examples on this page. If you are not
-familiar with `Eval`, it's worth reading [the Eval documentation](eval.html) first.)
+familiar with `Eval`, it's worth reading [the Eval documentation](eval.md) first.)
Our `updateUser` function takes in an existing user and some updates to perform.
It sanitises the inputs and updates the user model, but it delegates the
diff --git a/docs/datatypes/directory.conf b/docs/datatypes/directory.conf
new file mode 100644
index 0000000000..b44c76219c
--- /dev/null
+++ b/docs/datatypes/directory.conf
@@ -0,0 +1,25 @@
+laika.title = Data Types
+laika.navigationOrder = [
+ chain.md
+ const.md
+ contt.md
+ either.md
+ eithert.md
+ eval.md
+ freeapplicative.md
+ freemonad.md
+ functionk.md
+ id.md
+ ior.md
+ iort.md
+ kleisli.md
+ nel.md
+ nested.md
+ oneand.md
+ optiont.md
+ state.md
+ statet.md
+ validated.md
+ writer.md
+ writert.md
+]
\ No newline at end of file
diff --git a/docs/datatypes/either.md b/docs/datatypes/either.md
new file mode 100644
index 0000000000..81f289231a
--- /dev/null
+++ b/docs/datatypes/either.md
@@ -0,0 +1,10 @@
+{% laika.excludeFromNavigation = true %}
+
+# Either
+
+The `Either` type is provided by the Scala standard library, but Cats provides [syntax enrichment](../jump_start_guide.md#either-helpers) and typeclass instances
+to extend its functionality, including [Functor], [Applicative], [Monad] and
+[MonadError](../typeclasses/applicativemonaderror.md).
+
+If you would like to accumulate errors instead of the short-circuiting behavior of `Either`, see the
+[Parallel] typeclass, or the [Validated] data type.
diff --git a/docs/src/main/mdoc/datatypes/eithert.md b/docs/datatypes/eithert.md
similarity index 96%
rename from docs/src/main/mdoc/datatypes/eithert.md
rename to docs/datatypes/eithert.md
index 606c90a6a0..e724d693f0 100644
--- a/docs/src/main/mdoc/datatypes/eithert.md
+++ b/docs/datatypes/eithert.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "EitherT"
-section: "data"
-source: "core/src/main/scala/cats/data/EitherT.scala"
-scaladoc: "#cats.data.EitherT"
----
# EitherT
+API Documentation: @:api(cats.data.EitherT)
+
`Either` can be used for error handling in most situations. However, when
`Either` is placed into effectful types such as `Option` or`Future`, a large
amount of boilerplate is required to handle errors. For example, consider the
@@ -14,7 +9,7 @@ following program:
```scala mdoc
import scala.util.Try
-import cats.implicits._
+import cats.syntax.all._
def parseDouble(s: String): Either[String, Double] =
Try(s.toDouble).map(Right(_)).getOrElse(Left(s"$s is not a number"))
@@ -75,7 +70,7 @@ asynchronous division program can be rewritten as follows:
```scala mdoc:nest
import cats.data.EitherT
-import cats.implicits._
+import cats.syntax.all._
def divisionProgramAsync(inputA: String, inputB: String): EitherT[Future, String, Double] =
for {
diff --git a/docs/src/main/mdoc/datatypes/eval.md b/docs/datatypes/eval.md
similarity index 94%
rename from docs/src/main/mdoc/datatypes/eval.md
rename to docs/datatypes/eval.md
index 63f5431aca..c3e17fe351 100644
--- a/docs/src/main/mdoc/datatypes/eval.md
+++ b/docs/datatypes/eval.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Eval"
-section: "data"
-source: "core/src/main/scala/cats/Eval.scala"
-scaladoc: "#cats.Eval"
----
# Eval
+API Documentation: @:api(cats.Eval)
+
Eval is a data type for controlling synchronous evaluation.
Its implementation is designed to provide stack-safety at all times using a technique called trampolining.
@@ -28,7 +23,7 @@ First of the strategies is eager evaluation, we can construct an `Eval` eagerly
```scala mdoc
import cats.Eval
-import cats.implicits._
+import cats.syntax.all._
val eager = Eval.now {
@@ -86,7 +81,7 @@ Here we can see, that the expression is evaluated every time we call `.value`.
### Chaining lazy computations
One of the most useful applications of `Eval` is its ability to chain together computations in a stack-safe way.
-You can see one such usage when looking at the `foldRight` method found in [`Foldable`](../typeclasses/foldable.html).
+You can see one such usage when looking at the `foldRight` method found in [`Foldable`](../typeclasses/foldable.md).
Another great example are mutual tail-recursive calls:
```scala mdoc
diff --git a/docs/src/main/mdoc/datatypes/freeapplicative.md b/docs/datatypes/freeapplicative.md
similarity index 97%
rename from docs/src/main/mdoc/datatypes/freeapplicative.md
rename to docs/datatypes/freeapplicative.md
index 9d9082e18c..e5b8f9b5bc 100644
--- a/docs/src/main/mdoc/datatypes/freeapplicative.md
+++ b/docs/datatypes/freeapplicative.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "FreeApplicatives"
-section: "data"
-source: "free/src/main/scala/cats/free/FreeApplicative.scala"
-scaladoc: "#cats.free.FreeApplicative"
----
# Free Applicative
+API Documentation: @:api(cats.free.FreeApplicative)
+
`FreeApplicative`s are similar to `Free` (monads) in that they provide a nice way to represent
computations as data and are useful for building embedded DSLs (EDSLs). However, they differ
from `Free` in that the kinds of operations they support are limited, much like the distinction
@@ -44,7 +39,7 @@ Because a `FreeApplicative` only supports the operations of `Applicative`, we do
of a for-comprehension. We can however still use `Applicative` syntax provided by Cats.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
val prog: Validation[Boolean] = (size(5), hasNumber).mapN { case (l, r) => l && r}
```
@@ -55,7 +50,7 @@ at this point. To make our program useful we need to interpret it.
```scala mdoc:silent
import cats.Id
import cats.arrow.FunctionK
-import cats.implicits._
+import cats.syntax.all._
// a function that takes a string as input
type FromString[A] = String => A
@@ -93,7 +88,7 @@ write a validator that validates in parallel.
```scala mdoc:silent
import cats.data.Kleisli
-import cats.implicits._
+import cats.syntax.all._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
@@ -121,7 +116,7 @@ we can completely ignore the return type of the operation and return just a `Lis
```scala mdoc:silent
import cats.data.Const
-import cats.implicits._
+import cats.syntax.all._
type Log[A] = Const[List[String], A]
diff --git a/docs/src/main/mdoc/datatypes/freemonad.md b/docs/datatypes/freemonad.md
similarity index 96%
rename from docs/src/main/mdoc/datatypes/freemonad.md
rename to docs/datatypes/freemonad.md
index 9430583d76..d5c51e305b 100644
--- a/docs/src/main/mdoc/datatypes/freemonad.md
+++ b/docs/datatypes/freemonad.md
@@ -1,13 +1,7 @@
----
-layout: docs
-title: "FreeMonads"
-section: "data"
-source: "free/src/main/scala/cats/free/Free.scala"
-scaladoc: "#cats.free.Free"
----
-
# Free Monad
+API Documentation: @:api(cats.free.Free)
+
## What is it?
A *free monad* is a construction which allows you to build a *monad*
@@ -33,7 +27,7 @@ action. The next section uses `Free[_]` to create an embedded DSL
(Domain Specific Language).
If you're interested in the theory behind *free monads*, the
-[What is Free in theory?](#what-is-free-in-theory) section discusses free monads
+[What is Free in theory?](#for-the-curious-ones-what-is-free-in-theory) section discusses free monads
in terms of category theory.
### Study your topic
@@ -177,8 +171,7 @@ import cats.arrow.FunctionK
import cats.{Id, ~>}
import scala.collection.mutable
-// the program will crash if a key is not found,
-// or if a type is incorrectly specified.
+// the program will crash if a type is incorrectly specified.
def impureCompiler: KVStoreA ~> Id =
new (KVStoreA ~> Id) {
@@ -193,7 +186,7 @@ def impureCompiler: KVStoreA ~> Id =
()
case Get(key) =>
println(s"get($key)")
- kvs.get(key).map(_.asInstanceOf[A])
+ kvs.get(key).asInstanceOf[A]
case Delete(key) =>
println(s"delete($key)")
kvs.remove(key)
@@ -269,7 +262,7 @@ data-intensive tasks, as well as infinite processes such as streams.
The previous examples used an effectful natural transformation. This
works, but you might prefer folding your `Free` in a "purer" way. The
-[State](state.html) data structure can be used to keep track of the program
+[State](state.md) data structure can be used to keep track of the program
state in an immutable map, avoiding mutation altogether.
```scala mdoc:silent
@@ -281,7 +274,7 @@ val pureCompiler: KVStoreA ~> KVStoreState = new (KVStoreA ~> KVStoreState) {
fa match {
case Put(key, value) => State.modify(_.updated(key, value))
case Get(key) =>
- State.inspect(_.get(key).map(_.asInstanceOf[A]))
+ State.inspect(_.get(key).asInstanceOf[A])
case Delete(key) => State.modify(_ - key)
}
}
@@ -407,7 +400,7 @@ import DataSource._, Interacts._
val evaled: Unit = program.foldMap(interpreter)
```
-## For the curious ones: what is Free in theory?
+## For the curious ones: what is Free in theory?
Mathematically-speaking, a *free monad* (at least in the programming
language context) is a construction that is left adjoint to a
@@ -567,7 +560,7 @@ combined with `OptionT` for reducing boilerplate.
import cats.free._
import cats._
import cats.data._
-import cats.implicits._
+import cats.syntax.all._
import scala.util.Try
sealed trait Ctx[A]
diff --git a/docs/src/main/mdoc/datatypes/functionk.md b/docs/datatypes/functionk.md
similarity index 95%
rename from docs/src/main/mdoc/datatypes/functionk.md
rename to docs/datatypes/functionk.md
index a8cbace8ce..361b9d3530 100644
--- a/docs/src/main/mdoc/datatypes/functionk.md
+++ b/docs/datatypes/functionk.md
@@ -1,11 +1,7 @@
----
-layout: docs
-title: "FunctionK"
-section: "data"
-source: "core/src/main/scala/cats/arrow/FunctionK.scala"
-scaladoc: "#cats.arrow.FunctionK"
----
# FunctionK
+
+API Documentation: @:api(cats.arrow.FunctionK)
+
A `FunctionK` transforms values from one first-order-kinded type (a type that takes a single type
parameter, such as `List` or `Option`) into another first-order-kinded type. This transformation is
universal, meaning that a `FunctionK[List, Option]` will translate all `List[A]` values into an
@@ -60,7 +56,7 @@ def first(l: List[Int]): Option[Int] = l.headOption
The astute reader may have noticed that there's really no reason that this method needs to be tied directly to `Int`. We could use generics to make this a bit more general:
-```
+```scala mdoc:silent:reset
def first[A](l: List[A]): Option[A] = l.headOption
```
@@ -109,7 +105,7 @@ Being able to use `~>` as an alias for `FunctionK` parallels being able to use `
## Use-cases
-`FunctionK` tends to show up when there is abstraction over higher-kinds. For example, interpreters for [free monads](freemonad.html) and [free applicatives](freeapplicative.html) are represented as `FunctionK` instances.
+`FunctionK` tends to show up when there is abstraction over higher-kinds. For example, interpreters for [free monads](freemonad.md) and [free applicatives](freeapplicative.md) are represented as `FunctionK` instances.
## Types with more than one type parameter
diff --git a/docs/src/main/mdoc/datatypes/id.md b/docs/datatypes/id.md
similarity index 87%
rename from docs/src/main/mdoc/datatypes/id.md
rename to docs/datatypes/id.md
index 37c9c1c58a..78b6fb5c51 100644
--- a/docs/src/main/mdoc/datatypes/id.md
+++ b/docs/datatypes/id.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Id"
-section: "data"
-source: "core/src/main/scala/cats/package.scala"
-scaladoc: "#cats.Id$"
----
# Id
+API Documentation: [Id](@API_LINK_BASE@cats/index.html#Id[A]=A)
+
The identity monad can be seen as the ambient monad that encodes the
effect of having no effect. It is ambient in the sense that plain pure
values are values of `Id`.
@@ -29,7 +24,7 @@ val y: Int = x
```
Using this type declaration, we can treat our Id type constructor as a
-[`Monad`](../typeclasses/monad.html) and as a [`Comonad`](../typeclasses/comonad.html). The `pure`
+[`Monad`](../typeclasses/monad.md) and as a [`Comonad`](../typeclasses/comonad.md). The `pure`
method, which has type `A => Id[A]` just becomes the identity
function. The `map` method from `Functor` just becomes function
application:
diff --git a/docs/src/main/mdoc/datatypes/ior.md b/docs/datatypes/ior.md
similarity index 83%
rename from docs/src/main/mdoc/datatypes/ior.md
rename to docs/datatypes/ior.md
index e8ae82b15e..72502159b0 100644
--- a/docs/src/main/mdoc/datatypes/ior.md
+++ b/docs/datatypes/ior.md
@@ -1,14 +1,9 @@
----
-layout: docs
-title: "Ior"
-section: "data"
-source: "core/src/main/scala/cats/data/Ior.scala"
-scaladoc: "#cats.data.Ior"
----
# Ior
+API Documentation: @:api(cats.data.Ior)
+
`Ior` represents an inclusive-or relationship between two data types.
-This makes it very similar to the [`Either`](either.html) data type, which represents an "exclusive-or" relationship.
+This makes it very similar to the `Either` data type, which represents an "exclusive-or" relationship.
What this means, is that an `Ior[A, B]` (also written as `A Ior B`) can contain either an `A`, a `B`, or both an `A` and `B`.
Another similarity to `Either` is that `Ior` is right-biased,
which means that the `map` and `flatMap` functions will work on the right side of the `Ior`, in our case the `B` value.
@@ -33,7 +28,7 @@ val both = Ior.both("Warning", 3)
Cats also offers syntax enrichment for `Ior`. The `leftIor` and `rightIor` functions can be imported from `cats.syntax.ior._`:
```scala mdoc:nest
-import cats.implicits._
+import cats.syntax.all._
val right = 3.rightIor
@@ -41,14 +36,14 @@ val left = "Error".leftIor
```
-When we look at the `Monad` or `Applicative` instances of `Ior`, we can see that they actually requires a `Semigroup` instance on the left side.
-This is because `Ior` will actually accumulate failures on the left side, very similar to how the [`Validated`](validated.html) data type does.
+When we look at the `Monad` or `Applicative` instances of `Ior`, we can see that they actually require a `Semigroup` instance on the left side.
+This is because `Ior` will actually accumulate failures on the left side, very similar to how the [`Validated`](validated.md) data type does.
This means we can accumulate data on the left side while also being able to short-circuit upon the first left-side-only value.
For example, sometimes, we might want to accumulate warnings together with a valid result and only halt the computation on a "hard error"
Here's an example of how we might be able to do that:
```scala mdoc:reset-object:silent
-import cats.implicits._
+import cats.syntax.all._
import cats.data.{ NonEmptyChain => Nec, Ior}
@@ -105,7 +100,10 @@ validateUser("john.doe", "password").fold(
)
```
-Similar to [Validated](validated.html), there is also a type alias for using a `NonEmptyChain` on the left side.
+
+## Using with NonEmptyChain
+
+Similar to [Validated](validated.md), there is also a type alias for using a `NonEmptyChain` on the left side.
```scala mdoc:silent
import cats.data.NonEmptyChain
@@ -115,12 +113,13 @@ type IorNec[B, A] = Ior[NonEmptyChain[B], A]
```scala mdoc:nest
-import cats.implicits._, cats.data.NonEmptyChain
+import cats.syntax.all._, cats.data.NonEmptyChain
val left: IorNec[String, Int] = Ior.fromEither("Error".leftNec[Int])
```
+## Conversions
We can also convert our `Ior` to `Either`, `Validated` or `Option`.
All of these conversions will discard the left side value if both are available:
diff --git a/docs/src/main/mdoc/datatypes/iort.md b/docs/datatypes/iort.md
similarity index 98%
rename from docs/src/main/mdoc/datatypes/iort.md
rename to docs/datatypes/iort.md
index e72af38fe3..59eb56f28d 100644
--- a/docs/src/main/mdoc/datatypes/iort.md
+++ b/docs/datatypes/iort.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "IorT"
-section: "data"
-source: "core/src/main/scala/cats/data/IorT.scala"
-scaladoc: "#cats.data.IorT"
----
# IorT
+API Documentation: @:api(cats.data.IorT)
+
`IorT[F[_], A, B]` is a light wrapper on an `F[Ior[A, B]]`. Similar to
`OptionT[F[_], A]` and `EitherT[F[_], A, B]`, it is a monad transformer for
`Ior`, that can be more convenient to work with than using `F[Ior[A, B]]`
@@ -20,7 +15,7 @@ validating an address:
```scala mdoc:silent
import cats.data.Ior
import cats.data.{ NonEmptyChain => Nec }
-import cats.implicits._
+import cats.syntax.all._
import scala.util.{Success, Try}
type Logs = Nec[String]
diff --git a/docs/src/main/mdoc/datatypes/kleisli.md b/docs/datatypes/kleisli.md
similarity index 98%
rename from docs/src/main/mdoc/datatypes/kleisli.md
rename to docs/datatypes/kleisli.md
index e44420cddf..064a3f7ae9 100644
--- a/docs/src/main/mdoc/datatypes/kleisli.md
+++ b/docs/datatypes/kleisli.md
@@ -1,11 +1,7 @@
----
-layout: docs
-title: "Kleisli"
-section: "data"
-source: "core/src/main/scala/cats/data/Kleisli.scala"
-scaladoc: "#cats.data.Kleisli"
----
# Kleisli
+
+API Documentation: @:api(cats.data.Kleisli)
+
Kleisli enables composition of functions that return a monadic value, for instance an `Option[Int]`
or a `Either[String, List[Double]]`, without having functions take an `Option` or `Either` as a parameter,
which can be strange and unwieldy.
@@ -63,7 +59,7 @@ compose two `Kleisli`s much like we can two functions.
```scala mdoc:silent
import cats.FlatMap
-import cats.implicits._
+import cats.syntax.all._
final case class Kleisli[F[_], A, B](run: A => F[B]) {
def compose[Z](k: Kleisli[F, Z, A])(implicit F: FlatMap[F]): Kleisli[F, Z, B] =
@@ -75,7 +71,7 @@ Returning to our earlier example:
```scala mdoc:silent:nest
// Bring in cats.FlatMap[Option] instance
-import cats.implicits._
+import cats.syntax.all._
val parse: Kleisli[Option,String,Int] =
Kleisli((s: String) => if (s.matches("-?[0-9]+")) Some(s.toInt) else None)
@@ -128,7 +124,7 @@ An example of a `Monad` instance for `Kleisli` is shown below.
*Note*: the example below assumes usage of the [kind-projector compiler plugin](https://github.com/typelevel/kind-projector) and will not compile if it is not being used in a project.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
// We can define a FlatMap instance for Kleisli if the F[_] we chose has a FlatMap instance
// Note the input type and F are fixed, with the output type left free
diff --git a/docs/src/main/mdoc/datatypes/nel.md b/docs/datatypes/nel.md
similarity index 95%
rename from docs/src/main/mdoc/datatypes/nel.md
rename to docs/datatypes/nel.md
index 1876254d92..d3453c333a 100644
--- a/docs/src/main/mdoc/datatypes/nel.md
+++ b/docs/datatypes/nel.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "NonEmptyList"
-section: "data"
-source: "core/src/main/scala/cats/data/NonEmptyList.scala"
-scaladoc: "#cats.data.NonEmptyList"
----
# NonEmptyList
+API Documentation: @:api(cats.data.NonEmptyList)
+
## Motivation
We start with two examples of `NonEmptyList`s
@@ -14,7 +9,7 @@ We start with two examples of `NonEmptyList`s
### Usage in `Validated` and `Ior`
If you have had the opportunity of taking a look to
-[Validated](validated.html) or [Ior](ior.html), you'll find that a
+[Validated](validated.md) or [Ior](ior.md), you'll find that a
common case is to use `NonEmptyList` with one of these data
structures.
@@ -172,7 +167,7 @@ is only available for non-empty datastructures.
Here are some examples:
```scala mdoc
-import cats.implicits._
+import cats.syntax.all._
NonEmptyList.fromFoldable(List())
NonEmptyList.fromFoldable(List(1,2,3))
diff --git a/docs/src/main/mdoc/datatypes/nested.md b/docs/datatypes/nested.md
similarity index 93%
rename from docs/src/main/mdoc/datatypes/nested.md
rename to docs/datatypes/nested.md
index 3d801740f5..35502b5b1b 100644
--- a/docs/src/main/mdoc/datatypes/nested.md
+++ b/docs/datatypes/nested.md
@@ -1,12 +1,8 @@
----
-layout: docs
-title: "Nested"
-section: "data"
-source: "core/src/main/scala/cats/data/Nested.scala"
-scaladoc: "#cats.data.Nested"
----
+# Nested
-# Motivation
+API Documentation: @:api(cats.data.Nested)
+
+## Motivation
In day-to-day programming we quite often end up with data inside nested
effects, e.g. an integer inside an `Either`, which in turn is nested inside
@@ -29,7 +25,7 @@ x.map(_.map(_.toString))
```scala mdoc:silent
import cats.data.Nested
-import cats.implicits._
+import cats.syntax.all._
val nested: Nested[Option, Validated[String, *], Int] = Nested(Some(Valid(123)))
```
@@ -60,7 +56,7 @@ and `G[_]`. For example:
You can see the full list of these rules in the `Nested` companion object.
-## A more interesting example
+### A more interesting example
(courtesy of [Channing Walton and Luka Jacobowitz via
Twitter](https://twitter.com/LukaJacobowitz/status/1017355319473786880),
@@ -87,7 +83,7 @@ import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import cats.Applicative
import cats.data.Nested
-import cats.implicits._
+import cats.syntax.all._
def createUsers(userInfos: List[UserInfo]): Future[Either[List[String], List[User]]] =
userInfos.traverse(userInfo => Nested(createUser(userInfo))).value
diff --git a/docs/src/main/mdoc/datatypes/oneand.md b/docs/datatypes/oneand.md
similarity index 84%
rename from docs/src/main/mdoc/datatypes/oneand.md
rename to docs/datatypes/oneand.md
index 0f67ce7c46..c58859d46b 100644
--- a/docs/src/main/mdoc/datatypes/oneand.md
+++ b/docs/datatypes/oneand.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "OneAnd"
-section: "data"
-source: "core/src/main/scala/cats/data/OneAnd.scala"
-scaladoc: "#cats.data.OneAnd"
----
# OneAnd
+API Documentation: @:api(cats.data.OneAnd)
+
The `OneAnd[F[_],A]` data type represents a single element of type `A`
that is guaranteed to be present (`head`) and in addition to this a
second part that is wrapped inside an higher kinded type constructor
diff --git a/docs/src/main/mdoc/datatypes/optiont.md b/docs/datatypes/optiont.md
similarity index 89%
rename from docs/src/main/mdoc/datatypes/optiont.md
rename to docs/datatypes/optiont.md
index 82d0cd36da..e4780700f4 100644
--- a/docs/src/main/mdoc/datatypes/optiont.md
+++ b/docs/datatypes/optiont.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "OptionT"
-section: "data"
-source: "core/src/main/scala/cats/data/OptionT.scala"
-scaladoc: "#cats.data.OptionT"
----
# OptionT
+API Documentation: @:api(cats.data.OptionT)
+
`OptionT[F[_], A]` is a light wrapper on an `F[Option[A]]`. Speaking technically, it is a monad transformer for `Option`, but you don't need to know what that means for it to be useful. `OptionT` can be more convenient to work with than using `F[Option[A]]` directly.
## Reduce map boilerplate
@@ -38,7 +33,7 @@ As you can see, the implementations of all of these variations are very similar.
```scala mdoc:silent:nest
import cats.data.OptionT
-import cats.implicits._
+import cats.syntax.all._
val customGreetingT: OptionT[Future, String] = OptionT(customGreeting)
@@ -74,7 +69,7 @@ val result: Future[Option[String]] = ot.value // Future(Some("Hello Jane Doe"))
## From `A` to `OptionT[F,A]`
-If you have only an `A` and you wish to *lift* it into an `OptionT[F,A]` assuming you have an [`Applicative`]({{ site.baseurl }}/typeclasses/applicative.html) instance for `F` you can use `some` which is an alias for `pure`. There also exists a `none` method which can be used to create an `OptionT[F,A]`, where the `Option` wrapped `A` type is actually a `None`:
+If you have only an `A` and you wish to *lift* it into an `OptionT[F,A]` assuming you have an [`Applicative`](../typeclasses/applicative.md) instance for `F` you can use `some` which is an alias for `pure`. There also exists a `none` method which can be used to create an `OptionT[F,A]`, where the `Option` wrapped `A` type is actually a `None`:
```scala mdoc:silent
val greet: OptionT[Future,String] = OptionT.pure("Hola!")
diff --git a/docs/src/main/mdoc/datatypes/state.md b/docs/datatypes/state.md
similarity index 98%
rename from docs/src/main/mdoc/datatypes/state.md
rename to docs/datatypes/state.md
index baca8fff7c..2c19e67863 100644
--- a/docs/src/main/mdoc/datatypes/state.md
+++ b/docs/datatypes/state.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "State"
-section: "data"
-source: "core/src/main/scala/cats/data/StateT.scala"
-scaladoc: "#cats.data.StateT"
----
# State
+API Documentation: @:api(cats.data.IndexedStateT)
+
`State` is a structure that provides a functional approach to handling application state. `State[S, A]` is basically a function `S => (S, A)`, where `S` is the type that represents your state and `A` is the result the function produces. In addition to returning the result of type `A`, the function returns a new `S` value, which is the updated state.
## Robots
@@ -233,7 +228,7 @@ val nextLong: State[AsyncSeed, Future[Long]] = State { seed =>
Oops! That doesn't work: `State[S, A]` requires that we return a pure next `S` in the `State.apply` constructor. We could define `nextLong` as `State[Future[AsyncSeed], Future[Long]]`, but that would get us into even more trouble:
```scala mdoc:fail
-val nextLong: State[Future[AsyncSeed], Future[Long]] = State { seedF =>
+val nextLong: State[Future[AsyncSeed], Future[Long]] = State { seedF =>
seedF.map { seed =>
(seed.next, seed.long)
}
@@ -242,7 +237,7 @@ val nextLong: State[Future[AsyncSeed], Future[Long]] = State { seedF =>
The `seed` that `State.apply` passes in is now a `Future`, so we must map it. But we can't return a `Future[(Future[S], [A])]`; so what do we do?
-Luckily, `State[S, A]` is an alias for `StateT[Eval, S, A]` - a monad transformer defined as `StateT[F[_], S, A]`. This data type represents computations of the form `S => F[(S, A)]`.
+Luckily, `State[S, A]` is an alias for `StateT[Eval, S, A]` - a monad transformer defined as `StateT[F[_], S, A]`. This data type represents computations of the form `S => F[(S, A)]`.
If we plug in our concrete types, we get `AsyncSeed => Future[(AsyncSeed, A)]`, which is something we can work with:
```scala mdoc:silent
@@ -260,7 +255,7 @@ Now, what do we get back if we invoke `run` on our `nextLong` action?
nextLong.run(AsyncSeed(0))
```
-Since every intermediate computation returns a `Future`, the composite computation returns a `Future` as well. To summarize, `StateT[F[_], S, A]` allows us to interleave effects of type `F[_]` in the computations wrapped by it.
+Since every intermediate computation returns a `Future`, the composite computation returns a `Future` as well. To summarize, `StateT[F[_], S, A]` allows us to interleave effects of type `F[_]` in the computations wrapped by it.
It should be noted that different combinators on `StateT` impose different constraints on `F`; for example, `map` only requires that `F` has a `Functor` instance, but `flatMap` naturally requires `F` to have a `FlatMap` instance. Have a look at the method signatures for the details.
diff --git a/docs/datatypes/statet.md b/docs/datatypes/statet.md
new file mode 100644
index 0000000000..b275a463f9
--- /dev/null
+++ b/docs/datatypes/statet.md
@@ -0,0 +1,176 @@
+# StateT
+
+API Documentation: @:api(cats.data.IndexedStateT)
+
+`StateT[F[_], S, A]` is a data type that generalizes `State` with the
+ability to compose with effects in `F[_]`. Because `StateT` is defined
+in terms of `F`, it is a monad only if `F` is a monad. Additionally,
+`StateT` may acquire new capabilities via `F`: for example, if `F` is
+capable of error handling via `MonadThrow[F]`, then Cats derives an
+instance of `MonadThrow[StateT[F, S, *]]`.
+
+The type parameters are:
+
+- `F[_]` represents the effect in which the computation is performed.
+- `S` represents the underlying state, shared between each step of the
+ state machine.
+- `A` represents the return value.
+
+It can be seen as a way to add the capability to manipulate a shared
+state to an existing computation in the context of `F`.
+
+This definition could be confusing, but it will become clear after
+learning the `State` monad and by the example below.
+
+## StateT and State Relationship
+
+`StateT` is a monad transformer for
+[State](https://typelevel.org/cats/datatypes/state.html), in
+particular [State](https://typelevel.org/cats/datatypes/state.html) is
+defined as a `StateT` with
+[Eval](https://typelevel.org/cats/datatypes/eval.html) as the effect
+`F`.
+
+```scala mdoc:silent
+import cats.data.StateT
+import cats.Eval
+
+type State[S, A] = StateT[Eval, S, A]
+```
+
+Therefore, `StateT` exposes the same methods of
+[State](https://typelevel.org/cats/datatypes/state.html), such as:
+`modify`, `get` and `set`. Plus additional methods, that handles
+effectful computations, eg: `modifyF`, `setF` and `liftF`.
+
+## Example: Table Reservation System
+
+In this example, we are going to model a *Table Reservation System*. To
+do so, we need to keep track of the tables and the current
+reservations for each of them. The end-user can then try to insert a
+booking for a specific table and time. If such a table is available,
+then the booking is placed and the state is updated, otherwise, an
+error is returned.
+
+To simplify the logic, for each reservation we will just consider a
+single `LocalTime` starting at the beginning of the hour.
+
+Let's start with defining the type alias for the effect type:
+
+```scala mdoc:silent:reset
+import cats.data.{StateT, NonEmptyList}
+import cats.syntax.all._
+import java.time.LocalTime
+
+type ThrowableOr[A] = Either[Throwable, A]
+```
+
+We will use an `Either[Throwable, A]` to model either success `Right(a)` or failure `Left(ex)`.
+
+Now, we need to implement/define:
+- The type representing the reservation.
+- The type representing the state of the Table Reservation System. It
+ will wrap around a collection of Reservations.
+- An initial state, that will be just empty (no reservations).
+- A custom `Throwable` to be used in case of an error.
+- The logic for the booking insertion. We can take advantage of the
+method `modifyF` later on to apply it to the system state.
+
+In addition, we can implement a simple function that will evaluate a
+`NonEmptyList` of reservations, inserting them one by one.
+
+```scala mdoc:silent
+object TableReservationSystem {
+
+ final case class ReservationId(tableNumber: Int, hour: LocalTime)
+ final case class Reservation(id: ReservationId, name: String)
+ final case class Reservations(reservations: List[Reservation]) {
+ def insert(reservation: Reservation): ThrowableOr[Reservations] =
+ if (reservations.exists(r => r.id == reservation.id))
+ Left(new TableAlreadyReservedException(reservation))
+ else Right(Reservations(reservations :+ reservation))
+ }
+
+ final class TableAlreadyReservedException(
+ reservation: Reservation
+ ) extends RuntimeException(
+ s"${reservation.name} cannot be added because table number ${reservation.id.tableNumber} is already reserved for the ${reservation.id.hour}"
+ )
+
+ val emptyReservationSystem: Reservations = Reservations(List.empty)
+
+ def insertBooking(
+ reservation: Reservation
+ ): StateT[ThrowableOr, Reservations, Unit] =
+ StateT.modifyF[ThrowableOr, Reservations](_.insert(reservation))
+
+ def processBookings(
+ bookings: NonEmptyList[Reservation]
+ ): ThrowableOr[Reservations] =
+ bookings
+ .traverse_(insertBooking)
+ .runS(emptyReservationSystem)
+}
+```
+
+That's it, we can finally test the code above providing a simple
+example input and print out the result.
+
+```scala mdoc
+val bookings = NonEmptyList.of(
+ TableReservationSystem.Reservation(
+ TableReservationSystem
+ .ReservationId(tableNumber = 1, hour = LocalTime.parse("10:00:00")),
+ name = "Gandalf"
+ ),
+ TableReservationSystem.Reservation(
+ TableReservationSystem
+ .ReservationId(tableNumber = 2, hour = LocalTime.parse("10:00:00")),
+ name = "Legolas"
+ ),
+ TableReservationSystem.Reservation(
+ TableReservationSystem
+ .ReservationId(tableNumber = 1, hour = LocalTime.parse("12:00:00")),
+ name = "Frodo"
+ ),
+ TableReservationSystem.Reservation(
+ TableReservationSystem
+ .ReservationId(tableNumber = 2, hour = LocalTime.parse("12:00:00")),
+ name = "Bilbo"
+ ),
+ TableReservationSystem.Reservation(
+ TableReservationSystem
+ .ReservationId(tableNumber = 3, hour = LocalTime.parse("13:00:00")),
+ name = "Elrond"
+ ),
+ TableReservationSystem.Reservation(
+ TableReservationSystem
+ .ReservationId(tableNumber = 1, hour = LocalTime.parse("16:00:00")),
+ name = "Sauron"
+ ),
+ TableReservationSystem.Reservation(
+ TableReservationSystem
+ .ReservationId(tableNumber = 2, hour = LocalTime.parse("16:00:00")),
+ name = "Aragorn"
+ ),
+ TableReservationSystem.Reservation(
+ TableReservationSystem
+ .ReservationId(tableNumber = 2, hour = LocalTime.parse("18:00:00")),
+ name = "Gollum"
+ )
+)
+
+TableReservationSystem.processBookings(bookings)
+
+TableReservationSystem.processBookings(
+ bookings :+ TableReservationSystem.Reservation(
+ TableReservationSystem
+ .ReservationId(tableNumber = 1, hour = LocalTime.parse("16:00:00")),
+ name = "Saruman"
+ )
+)
+```
+
+The full source code of this example can be found at this
+[gist](https://gist.github.com/benkio/baa4fe1d50751cd602c4175f1bb39f4d)
+or [scastie](https://scastie.scala-lang.org/YhJmET6PRJKvrZTfrZJkbQ)
diff --git a/docs/src/main/mdoc/datatypes/validated.md b/docs/datatypes/validated.md
similarity index 90%
rename from docs/src/main/mdoc/datatypes/validated.md
rename to docs/datatypes/validated.md
index 4f78b4fc0b..60fb9532d2 100644
--- a/docs/src/main/mdoc/datatypes/validated.md
+++ b/docs/datatypes/validated.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Validated"
-section: "data"
-source: "core/src/main/scala/cats/data/Validated.scala"
-scaladoc: "#cats.data.Validated"
----
# Validated
+API Documentation: @:api(cats.data.Validated)
+
Imagine you are filling out a web form to signup for an account. You input your username and password and submit.
Response comes back saying your username can't have dashes in it, so you make some changes and resubmit. Can't
have special characters either. Change, resubmit. Passwords need to have at least one capital letter. Change,
@@ -77,7 +72,7 @@ case object AgeIsInvalid extends DomainValidation {
We have our `RegistrationData` case class that will hold the information the user has submitted, alongside the definition of the error model that we'll be using for displaying the possible errors of every field. Now, let's explore the proposed implementation:
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
sealed trait FormValidator {
def validateUserName(userName: String): Either[DomainValidation, String] =
@@ -174,7 +169,7 @@ Time to do some refactoring! We're going to try a `Validated` approach:
```scala mdoc:silent
import cats.data._
import cats.data.Validated._
-import cats.implicits._
+import cats.syntax.all._
def validateUserName(userName: String): Validated[DomainValidation, String] = FormValidator.validateUserName(userName).toValidated
@@ -203,7 +198,7 @@ This datatype, as with `Either` has two projections: `Valid` and `Invalid`, anal
Remember that our goal is to get all the validation errors for displaying it to the user, but you'll find that this approach won't compile, as you can see in the previous snippet. Why?
-Without diving into details about monads, a for-comprehension uses the `flatMap` method for composition. Monads like `Either` can be composed in that way, but the thing with `Validated` is that it isn't a monad, but an [_Applicative Functor_](../typeclasses/applicativetraverse.html).
+Without diving into details about monads, a for-comprehension uses the `flatMap` method for composition. Monads like `Either` can be composed in that way, but the thing with `Validated` is that it isn't a monad, but an [_Applicative Functor_](../typeclasses/applicativetraverse.md).
That's why you see the message: `error: value flatMap is not a member of cats.data.Validated[DomainValidation,String]`.
So, how do we do here?
@@ -252,7 +247,7 @@ Let's see what changed here:
2. `ValidatedNec[DomainValidation, A]` is an alias for `Validated[NonEmptyChain[DomainValidation], A]`. When you use `ValidatedNec` you're stating that your accumulative structure will be a `NonEmptyChain`. With `Validated`, you have the choice about which data structure you want for reporting the errors (more on that soon).
3. We've declared the type alias `ValidationResult` that conveniently expresses the return type of our validation.
4. `.validNec` and `.invalidNec` combinators lets you _lift_ the success or failure in their respective container (either a `Valid` or `Invalid[NonEmptyChain[A]]`).
-5. The [applicative](../typeclasses/applicative.html) syntax `(a, b, c, ...).mapN(...)` provides us a way to accumulatively apply the validation functions and yield a product with their successful result or the accumulated errors in the `NonEmptyChain`. Then, we transform that product with `mapN` into a valid instance of `RegistrationData`.
+5. The [applicative](../typeclasses/applicative.md) syntax `(a, b, c, ...).mapN(...)` provides us a way to accumulatively apply the validation functions and yield a product with their successful result or the accumulated errors in the `NonEmptyChain`. Then, we transform that product with `mapN` into a valid instance of `RegistrationData`.
**Deprecation notice:** since Cats `1.0.0-MF` the cartesian syntax `|@|` for applicatives is deprecated. If you're using `0.9.0` or less, you can use the syntax: `(a |@| b |@| ...).map(...)`.
@@ -284,7 +279,7 @@ Sweet success! Now you can take your validation process to the next level!
As previously stated, `ValidatedNec[DomainValidation, A]` is an alias for `Validated[NonEmptyChain[DomainValidation], A]`. Typically, you'll see that `Validated` is accompanied by a `NonEmptyChain` when it comes to accumulation. The thing here is that you can define your own accumulative data structure and you're not limited to the aforementioned construction.
-For doing this, you have to provide a `Semigroup` instance. `NonEmptyChain`, by definition has its own `Semigroup`. For those who don't know what a `Semigroup` is, you can find out more [here](../typeclasses/semigroup.html).
+For doing this, you have to provide a `Semigroup` instance. `NonEmptyChain`, by definition has its own `Semigroup`. For those who don't know what a `Semigroup` is, you can find out more [here](../typeclasses/semigroup.md).
#### Accumulative Structures
@@ -461,7 +456,7 @@ Time to parse.
```scala mdoc:silent:nest
import cats.SemigroupK
import cats.data.NonEmptyChain
-import cats.implicits._
+import cats.syntax.all._
case class ConnectionParams(url: String, port: Int)
@@ -596,8 +591,63 @@ validatedMonad.tuple2(Validated.invalidNec[String, Int]("oops"), Validated.inval
```
This one short circuits! Therefore, if we were to define a `Monad` (or `FlatMap`) instance for `Validated` we would
-have to override `ap` to get the behavior we want. But then the behavior of `flatMap` would be inconsistent with
-that of `ap`, not good. Therefore, `Validated` has only an `Applicative` instance.
+have to override `ap` to get the behavior we want.
+
+```scala mdoc:silent:nest
+import cats.Monad
+
+implicit def accumulatingValidatedMonad[E: Semigroup]: Monad[Validated[E, *]] =
+ new Monad[Validated[E, *]] {
+ def flatMap[A, B](fa: Validated[E, A])(f: A => Validated[E, B]): Validated[E, B] =
+ fa match {
+ case Valid(a) => f(a)
+ case i@Invalid(_) => i
+ }
+
+ def pure[A](x: A): Validated[E, A] = Valid(x)
+
+ @annotation.tailrec
+ def tailRecM[A, B](a: A)(f: A => Validated[E, Either[A, B]]): Validated[E, B] =
+ f(a) match {
+ case Valid(Right(b)) => Valid(b)
+ case Valid(Left(a)) => tailRecM(a)(f)
+ case i@Invalid(_) => i
+ }
+
+ override def ap[A, B](f: Validated[E, A => B])(fa: Validated[E, A]): Validated[E, B] =
+ (fa, f) match {
+ case (Valid(a), Valid(fab)) => Valid(fab(a))
+ case (i@Invalid(_), Valid(_)) => i
+ case (Valid(_), i@Invalid(_)) => i
+ case (Invalid(e1), Invalid(e2)) => Invalid(Semigroup[E].combine(e1, e2))
+ }
+ }
+```
+
+But then the behavior of `flatMap` would be inconsistent with that of `ap`, and this will violate one of the [FlatMap laws](https://github.com/typelevel/cats/blob/main/laws/src/main/scala/cats/laws/FlatMapLaws.scala), `flatMapConsistentApply`:
+
+```scala
+// the `<->` operator means "is equivalent to" and returns a data structure
+// `IsEq` that is used to verify the equivalence of the two expressions
+def flatMapConsistentApply[A, B](fa: F[A], fab: F[A => B]): IsEq[F[B]] =
+ fab.ap(fa) <-> fab.flatMap(f => fa.map(f))
+```
+
+```scala mdoc:silent
+import cats.laws._
+
+val flatMapLawsForAccumulatingValidatedMonad =
+ FlatMapLaws[Validated[NonEmptyChain[String], *]](accumulatingValidatedMonad)
+
+val fa = Validated.invalidNec[String, Int]("oops")
+val fab = Validated.invalidNec[String, Int => Double]("Broken function")
+```
+
+```scala mdoc
+flatMapLawsForAccumulatingValidatedMonad.flatMapConsistentApply(fa , fab)
+```
+
+Therefore, `Validated` has only an `Applicative` instance.
## `Validated` vs `Either`
@@ -625,8 +675,6 @@ val houseNumber = config.parse[Int]("house_number").andThen{ n =>
The `withEither` method allows you to temporarily turn a `Validated` instance into an `Either` instance and apply it to a function.
```scala mdoc:silent
-import cats.implicits._ // get Either#flatMap
-
def positive(field: String, i: Int): Either[ConfigError, Int] = {
if (i >= 0) Right(i)
else Left(ParseError(field))
diff --git a/docs/src/main/mdoc/datatypes/writer.md b/docs/datatypes/writer.md
similarity index 79%
rename from docs/src/main/mdoc/datatypes/writer.md
rename to docs/datatypes/writer.md
index b935058223..7d1cb39f4d 100644
--- a/docs/src/main/mdoc/datatypes/writer.md
+++ b/docs/datatypes/writer.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Writer"
-section: "data"
-source: "core/src/main/scala/cats/data/package.scala"
-scaladoc: "#cats.data.Writer"
----
# Writer
+API Documentation: @:api(cats.data.WriterT)
+
The `Writer[L, A]` datatype represents a computation that produces a
tuple containing a value of type `L` and one of type `A`. Usually, the
value `L` represents a description of the computation. A typical
@@ -22,16 +17,16 @@ multiple ways. See the [Operations section](#operations)
When two functions are composed together, e.g. using `flatMap`, the logs
of both functions will be combined using an implicit
- [Semigroup](https://typelevel.org/cats/typeclasses/semigroup.html).
+ [Semigroup](../typeclasses/semigroup.md).
## Operations
The `Writer` datatype provides a set of functions that are similar to
the ones from the
-[Monad](https://typelevel.org/cats/typeclasses/monad.html)
+[Monad](../typeclasses/monad.md)
typeclass. In fact, they share the same name and the same signature,
but have an additional requirement of a
-[`Semigroup[L]`](https://typelevel.org/cats/typeclasses/semigroup.html)
+[`Semigroup[L]`](../typeclasses/semigroup.md)
that allows the log merging.
`map` effects only the value, keeping the log side untouched. Plus, here we show `run`
@@ -48,7 +43,7 @@ mapExample.run
`ap` allows applying a function, wrapped into a Writer. It works
exactly like the `Applicative` as expected, but notice how the logs
-are combined using the [`Semigroup[String]`](https://typelevel.org/cats/typeclasses/semigroup.html).
+are combined using the [`Semigroup[String]`](../typeclasses/semigroup.md).
```scala mdoc
val apExampleValue = Writer("ap value", 10)
@@ -78,13 +73,13 @@ Apart from those, `Writer` comes with some specific functions to manage
the log side of the computation:
`tell`
-: Append a value to the log side. It requires a [`Semigroup[L]`](https://typelevel.org/cats/typeclasses/semigroup.html).
+: Append a value to the log side. It requires a [`Semigroup[L]`](../typeclasses/semigroup.md).
`swap`
: Exchange the two values of the `Writer`.
`reset`
-: Delete the log side. It requires a [`Monoid[L]`](https://typelevel.org/cats/typeclasses/monoid.html) since it uses the `empty` value of the monoid.
+: Delete the log side. It requires a [`Monoid[L]`](../typeclasses/monoid.md) since it uses the `empty` value of the monoid.
`value`
: Returns only the value of the `Writer`
@@ -130,13 +125,13 @@ type Writer[L, V] = WriterT[Id, L, V]
So, all the [Operations](#operations) defined in the previous section
are actually coming from the [WriterT
-datatype](https://typelevel.org/cats/datatypes/writert.html)
+datatype](writert.md)
-Most of the [`WriterT`](https://typelevel.org/cats/datatypes/writert.html) functions require a
-[`Functor[F]`](https://typelevel.org/cats/typeclasses/functor.html) or
-[`Monad[F]`](https://typelevel.org/cats/typeclasses/monad.html)
+Most of the [`WriterT`](writert.md) functions require a
+[`Functor[F]`](../typeclasses/functor.md) or
+[`Monad[F]`](../typeclasses/monad.md)
instance. However, Cats provides all the necessary instances for the
-[`Id`](https://typelevel.org/cats/datatypes/id.html) type, therefore
+[`Id`](id.md) type, therefore
we don't have to worry about them.
## Example
@@ -149,7 +144,7 @@ applies a bunch of Math operations, logging each one of them.
import cats.data.Writer
import scala.math.sqrt
-val writer1: Writer[String, Double] = Writer.value(5.0).tell("Initial value ")
+val writer1: Writer[String, Double] = Writer.value[String, Double](5.0).tell("Initial value ")
val writer2: Writer[String, Double => Double] = Writer("sqrt ", (i: Double) => sqrt(i))
val writer3: Double => Writer[String, Double] = (x: Double) => Writer("add 1 ", x + 1)
val writer4: Writer[String, Double => Double] = Writer("divided by 2 ", (x: Double) => x / 2)
diff --git a/docs/src/main/mdoc/datatypes/writert.md b/docs/datatypes/writert.md
similarity index 78%
rename from docs/src/main/mdoc/datatypes/writert.md
rename to docs/datatypes/writert.md
index da46e82c71..d793d2cea9 100644
--- a/docs/src/main/mdoc/datatypes/writert.md
+++ b/docs/datatypes/writert.md
@@ -1,14 +1,9 @@
----
-layout: docs
-title: "WriterT"
-section: "data"
-source: "core/src/main/scala/cats/data/WriterT.scala"
-scaladoc: "#cats.data.WriterT"
----
# WriterT
+API Documentation: @:api(cats.data.WriterT)
+
`WriterT[F[_], L, V]` is a type wrapper on an `F[(L,
-V)]`. Speaking technically, it is a monad transformer for [`Writer`](https://typelevel.org/cats/datatypes/writer.html),
+V)]`. Speaking technically, it is a monad transformer for [`Writer`](writer.md),
but you don't need to know what that means for it to be
useful.
@@ -16,8 +11,8 @@ useful.
`WriterT` can be more convenient to work with than using
`F[Writer[L, V]]` directly, because it exposes operations that allow
-you to work with the values of the inner [`Writer`](https://typelevel.org/cats/datatypes/writer.html) (`L` and
-`V`) abstracting both the `F` and [`Writer`](https://typelevel.org/cats/datatypes/writer.html).
+you to work with the values of the inner [`Writer`](writer.md) (`L` and
+`V`) abstracting both the `F` and [`Writer`](writer.md).
For example, `map` allow you to transform the inner `V` value, getting
back a `WriterT` that wraps around it.
@@ -30,13 +25,13 @@ WriterT[Option, String, Int](Some(("value", 10))).map(x => x * x)
Plus, when composing multiple `WriterT` computations, those will be
composed following the same behaviour of a
-[`Writer`](https://typelevel.org/cats/datatypes/writer.html) and the
-generic `F`. Let's see two examples with `Option` and [`Either`](https://typelevel.org/cats/datatypes/either.html): if
+[`Writer`](writer.md) and the
+generic `F`. Let's see two examples with `Option` and `Either`: if
one of the computations has a `None` or a `Left`, the whole
computation will return a `None` or a `Left` since the way the two
types compose typically behaves that way. Moreover, when the
computation succeed, the logging side of the
-[`Writer`](https://typelevel.org/cats/datatypes/writer.html)s will be
+[`Writer`](writer.md)s will be
combined.
```scala mdoc:silent
@@ -80,23 +75,23 @@ for {
Just for completeness, we can have a look at the same example, but
with
-[`Validated`](https://typelevel.org/cats/datatypes/validated.html)
+[`Validated`](validated.md)
since it as a slightly different behaviour than
-[`Either`](https://typelevel.org/cats/datatypes/either.html). Instead
+`Either`. Instead
of short-circuiting when the first error is encountered,
-[`Validated`](https://typelevel.org/cats/datatypes/validated.html)
+[`Validated`](validated.md)
will accumulate all the errors. In the following example, you can see
how this behaviour is respected when
-[`Validated`](https://typelevel.org/cats/datatypes/validated.html) is
+[`Validated`](validated.md) is
wrapped as the `F` type of a `WriterT`. In addition, notice
how `flatMap` and for comprehension can't be used in this case, since
-[`Validated`](https://typelevel.org/cats/datatypes/validated.html)
-only extends [`Applicative`](https://typelevel.org/cats/typeclasses/applicative.html), but not [`Monad`](https://typelevel.org/cats/typeclasses/monad.html).
+[`Validated`](validated.md)
+only extends [`Applicative`](../typeclasses/applicative.md), but not [`Monad`](../typeclasses/monad.md).
```scala mdoc:silent
import cats.data.Validated
import cats.data.Validated.{Invalid, Valid}
-import cats.implicits._
+import cats.syntax.all._
val validatedWriterT1 : WriterT[Validated[String, *], String, Int] = WriterT(Valid(("writerT value 1", 123)))
val validatedWriterT2 : WriterT[Validated[String, *], String, Int] = WriterT(Valid(("writerT value 1", 123)))
@@ -138,9 +133,9 @@ type starting from the full wrapped value.
`liftF[F[_], L, V](fv: F[V])(implicit monoidL: Monoid[L], F: Applicative[F]): WriterT[F, L, V]`
: This function allows you to build the datatype starting from the
value `V` wrapped into an `F`. Notice how it requires:
-* [`Monoid[L]`](https://typelevel.org/cats/typeclasses/monoid.html), since it uses the `empty` value from the typeclass.
+* [`Monoid[L]`](../typeclasses/monoid.md), since it uses the `empty` value from the typeclass.
to fill the `L` value not specified in the input.
-* [`Applicative[F]`](https://typelevel.org/cats/typeclasses/applicative.html) to modify the inner value.
+* [`Applicative[F]`](../typeclasses/applicative.md) to modify the inner value.
```scala mdoc:nest
import cats.instances.option._
@@ -151,8 +146,8 @@ to fill the `L` value not specified in the input.
```
`put[F[_], L, V](v: V)(l: L)(implicit applicativeF: Applicative[F]): WriterT[F, L, V]`
-: As soon as there is an [`Applicative`](https://typelevel.org/cats/typeclasses/applicative.html) instance of `F`, this function
-creates the datatype starting from the inner [`Writer`](https://typelevel.org/cats/datatypes/writer.html)'s values.
+: As soon as there is an [`Applicative`](../typeclasses/applicative.md) instance of `F`, this function
+creates the datatype starting from the inner [`Writer`](writer.md)'s values.
```scala mdoc:nest
WriterT.put[Option, String, Int](123)("initial value")
@@ -168,14 +163,14 @@ creates the datatype starting from the inner [`Writer`](https://typelevel.org/ca
## Operations
In the [Writer
-definition](https://typelevel.org/cats/datatypes/writer.html#definition)
+definition](writer.md#definition)
section, we showed how it is actually a `WriterT`. Therefore, all the
operations described into [Writer
-operations](https://typelevel.org/cats/datatypes/writer.html#operations)
+operations](writer.md#operations)
are valid for `WriterT` as well.
The only aspect we want to remark here is the following sentence from
-[`Writer`](https://typelevel.org/cats/datatypes/writer.html)'s page:
+[`Writer`](writer.md)'s page:
> Most of the `WriterT` functions require a `Functor[F]` or
> `Monad[F]` instance. However, Cats provides all the necessary
diff --git a/docs/directory.conf b/docs/directory.conf
new file mode 100644
index 0000000000..7632d07504
--- /dev/null
+++ b/docs/directory.conf
@@ -0,0 +1,20 @@
+laika.navigationOrder = [
+ index.md
+ typeclasses.md
+ datatypes.md
+ algebra.md
+ alleycats.md
+ motivations.md
+ resources_for_learners.md
+ jump_start_guide.md
+ imports.md
+ faq.md
+ CONTRIBUTING.md
+ ADOPTERS.md
+ colophon.md
+ nomenclature.md
+ guidelines.md
+ typelevelEcosystem.md
+ typeclasses
+ datatypes
+]
\ No newline at end of file
diff --git a/docs/src/main/mdoc/faq.md b/docs/faq.md
similarity index 66%
rename from docs/src/main/mdoc/faq.md
rename to docs/faq.md
index dd0109b1c2..395b7473e2 100644
--- a/docs/src/main/mdoc/faq.md
+++ b/docs/faq.md
@@ -1,35 +1,13 @@
----
-layout: page
-title: "FAQ"
-section: "faq"
-position: 40
----
+{% laika.title = FAQ %}
# Frequently Asked Questions
-## Questions
- * [What imports do I need?](#what-imports)
- * [I am new to pure functional programming, what quick wins can I get from Cats?](#quick-wins)
- * [What is the difference between Cats and Scalaz?](#diff-scalaz)
- * [Where is right-biased `Either`?](#either)
- * [Why is the compiler having trouble with types with more than one type parameter?](#si-2712)
- * [Why can't the compiler find implicit instances for Future?](#future-instances)
- * [Where are implicit instances for `Seq`](seq-instances)
- * [Why is some example code not compiling for me?](#example-compile)
- * [How can I turn my List of `` into a `` of a list?](#traverse)
- * [Where is `ListT`?](#listt)
- * [Where are `Applicative`s for monad transformers?](#applicative-monad-transformers)
- * [Where is `IO`/`Task`?](#task)
- * [What does `@typeclass` mean?](#simulacrum)
- * [What do types like `?` and `λ` mean?](#kind-projector)
- * [What is `tailRecM`?](#tailrecm)
- * [What does this symbol mean?](#symbol)
- * [How can I test instances against their type classes' laws?](#law-testing)
- * [How can I help?](#contributing)
- * [Why aren't monad transformers like `OptionT` and `EitherT` covariant like `Option` and `Either`?](#monad-transformer-variance)
- * [How to try Cats in a REPL?](#ammonite)
-
-## What imports do I need?
+@:navigationTree {
+ entries = [ { target = "faq.md", depth = 2 } ]
+}
+
+
+## What imports do I need?
The easiest approach to Cats imports is to import everything that's commonly needed:
@@ -39,19 +17,19 @@ import cats.data._
import cats.syntax.all._
```
-This should be all that you need, but if you'd like to learn more about the details of imports than you can check out the [import guide](typeclasses/imports.html).
+This should be all that you need, but if you'd like to learn more about the details of imports than you can check out the [import guide](imports.md).
-## I am new to pure functional programming, what quick wins can I get from Cats?
+## I am new to pure functional programming, what quick wins can I get from Cats?
-Please refer to the [jump start guide]({{ site.baseurl }}/jump_start_guide.html).
+Please refer to the [jump start guide](jump_start_guide.md).
-## What is the difference between Cats and Scalaz?
+## What is the difference between Cats and Scalaz?
-Cats and [Scalaz](https://github.com/scalaz/scalaz) have the same goal: to facilitate pure functional programming in Scala applications. However the underlying core strategy is different; Scalaz took the approach of trying to provide a single batteries-included *standard library* for FP that powers the Scala applications. Cats, on the other hand, aims to help build an [ecosystem](/cats/#ecosystem) of pure FP libraries by providing a solid and stable foundation; these libraries can have their own styles and personalities, competing with each other, while at the same time playing nice. It is through this ecosystem of FP libraries (cats included) that Scala applications can be powered with "FP awesome-ness" and beyond by picking whatever best fit their needs.
+Cats and [Scalaz](https://github.com/scalaz/scalaz) have the same goal: to facilitate pure functional programming in Scala applications. However the underlying core strategy is different; Scalaz took the approach of trying to provide a single batteries-included *standard library* for FP that powers the Scala applications. Cats, on the other hand, aims to help build an [ecosystem](typelevelEcosystem.md) of pure FP libraries by providing a solid and stable foundation; these libraries can have their own styles and personalities, competing with each other, while at the same time playing nice. It is through this ecosystem of FP libraries (cats included) that Scala applications can be powered with "FP awesome-ness" and beyond by picking whatever best fit their needs.
-Based on this core strategy, Cats takes a [modular](/cats/motivations#modularity) approach and focuses on providing core, [binary compatible](/cats/#binary-compatibility-and-versioning), [approachable](/cats/motivations#approachability) and [efficient](/cats/motivations#efficiency) abstractions. It provides a welcoming and supportive environment for the [user community](https://gitter.im/typelevel/cats) governed by the [Scala code of conduct](https://www.scala-lang.org/conduct/). It also takes great effort in supplying a comprehensive and beginner-friendly [documentation](/cats/#documentation).
+Based on this core strategy, Cats takes a [modular](motivations.md#modularity) approach and focuses on providing core, [binary compatible](index.md#binary-compatibility-and-versioning), [approachable](motivations.md#approachability) and [efficient](motivations.md#efficiency) abstractions. It provides a welcoming and supportive environment for the [user community](https://discord.gg/XF3CXcMzqD) governed by the [Scala Code of Conduct](https://www.scala-lang.org/conduct/). It also takes great effort in supplying a comprehensive and beginner-friendly [documentation](motivations.md#documentation).
-## Where is right-biased Either?
+## Where is right-biased Either?
Up through Cats 0.7.x we had `cats.data.Xor`, which was effectively `scala.util.Either`, but right-biased by default and with
a bunch of useful combinators around it. In Scala 2.12.x `Either`
[became right-biased](https://github.com/scala/scala/pull/5135) so we revisited the use of `Xor` and
@@ -59,38 +37,38 @@ a bunch of useful combinators around it. In Scala 2.12.x `Either`
fill in the gaps in the `scala.util.Either` API via
[syntax enrichment](https://github.com/typelevel/cats/blob/main/core/src/main/scala/cats/syntax/either.scala).
-This syntax and the type class instances for `Either` can be imported using `cats.implicits._`, which will also bring in syntactic enrichment and instances for other standard library types, or you can import them individually with `cats.syntax.either._` and `cats.instances.either._`.
+This syntax and the type class instances for `Either` can be imported using `cats.syntax._`, which will also bring in syntactic enrichment and instances for other standard library types, or you can import only the `Either` enrichment with `cats.syntax.either._`.
-There are a few minor mismatches between `Xor` and `Either`. For example, in some cases you may need to specify a type parameter for an enrichment method on `Either` (such as `leftMap`) even though it was properly inferred for `Xor`. See the [`Either` section of this guide](http://typelevel.org/cats/datatypes/either.html#either-in-the-small-either-in-the-large) for more information about these issues.
+There are a few minor mismatches between `Xor` and `Either`. For example, in some cases you may need to specify a type parameter for an enrichment method on `Either` (such as `leftMap`) even though it was properly inferred for `Xor`, due to `Either` having covariant type parameters.
Similarly, `cats.data.XorT` has been replaced with `cats.data.EitherT`, although since this is a type defined in Cats, you don't need to import syntax or instances for it (although you may need imports for the underlying monad).
-## Why is the compiler having trouble with types with more than one type parameter?
+## Why is the compiler having trouble with types with more than one type parameter?
-When you encounter a situation where the same code works fine with a type with one type parameter, e.g. List[A], but doesn't work with types with more than one, e.g. Either[A, B], you probably hit [SI-2712](https://issues.scala-lang.org/browse/SI-2712). Without going into the details, it's highly recommended to enable a partial SI-2712 fix in your project. The easiest way to achieve that is through this [sbt plugin](https://github.com/fiadliel/sbt-partial-unification).
+When you encounter a situation where the same code works fine with a type with one type parameter, e.g. `List[A]`, but doesn't work with types with more than one, e.g. `Either[A, B]`, you probably hit [SI-2712](https://issues.scala-lang.org/browse/SI-2712). Without going into the details, it's highly recommended to enable a partial SI-2712 fix in your project. The easiest way to achieve that is through this [sbt plugin](https://github.com/fiadliel/sbt-partial-unification).
Cats used to provide mitigation to this issue semi-transparently, but given the fact that the fix is now mainstream, we decided to drop that mitigation machinery in favor of reducing the complexity. See this [issue](https://github.com/typelevel/cats/issues/1073) for details.
-## Why is some example code not compiling for me?
+## Why is some example code not compiling for me?
A portion of example code requires either the [Kind-projector](https://github.com/typelevel/kind-projector) compiler plugin or partial unification turned on in scalac. The easiest way to turn partial unification on is through this [sbt plugin](https://github.com/fiadliel/sbt-partial-unification).
-## Why can't the compiler find implicit instances for Future?
+## Why can't the compiler find implicit instances for Future?
-If you have already followed the [imports advice](#what-imports) but are still getting error messages like `could not find implicit value for parameter e: cats.Monad[scala.concurrent.Future]` or `value |+| is not a member of scala.concurrent.Future[Int]`, then make sure that you have an implicit `scala.concurrent.ExecutionContext` in scope. The easiest way to do this is to `import scala.concurrent.ExecutionContext.Implicits.global`, but note that you may want to use a different execution context for your production application.
+If you have already followed the [imports advice](#what-imports-do-i-need) but are still getting error messages like `could not find implicit value for parameter e: cats.Monad[scala.concurrent.Future]` or `value |+| is not a member of scala.concurrent.Future[Int]`, then make sure that you have an implicit `scala.concurrent.ExecutionContext` in scope. The easiest way to do this is to `import scala.concurrent.ExecutionContext.Implicits.global`, but note that you may want to use a different execution context for your production application.
-## Where are implicit instances for `Seq`?
+## Where are implicit instances for `Seq`?
As of `cats-2.3`, instances for `collection.immutable.Seq` are provided by cats.
Mind that, up to `scala-2.12`, `Seq` was an alias for `collection.Seq` and lawful instances can't be provided for it due to its potential mutability.
In `scala-2.13`, `Seq` was changed to `collection.immutable.Seq` which greatly improves `Seq`'s interoperability with cats.
-## How can I turn my List of `` into a `` of a list?
+## How can I turn my List of `` into a `` of a list?
-It's really common to have a `List` of values with types like `Option`, `Either`, or `Validated` that you would like to turn "inside out" into an `Option` (or `Either` or `Validated`) of a `List`. The `sequence` and `traverse` methods are _really_ handy for this. You can read more about them in the [Traverse documentation]({{ site.baseurl }}/typeclasses/traverse.html).
+It's really common to have a `List` of values with types like `Option`, `Either`, or `Validated` that you would like to turn "inside out" into an `Option` (or `Either` or `Validated`) of a `List`. The `sequence` and `traverse` methods are _really_ handy for this. You can read more about them in the [Traverse documentation](typeclasses/traverse.md).
-## Where is ListT?
+## Where is ListT?
-There are monad transformers for various types, such as [OptionT]({{ site.baseurl }}/datatypes/optiont.html), so people often wonder why there isn't a `ListT`. For example, in the following example, people might reach for `ListT` to simplify making nested `map` and `exists` calls:
+There are monad transformers for various types, such as [OptionT](datatypes/optiont.md), so people often wonder why there isn't a `ListT`. For example, in the following example, people might reach for `ListT` to simplify making nested `map` and `exists` calls:
```scala mdoc:reset:silent
val l: Option[List[Int]] = Some(List(1, 2, 3, 4, 5))
@@ -109,7 +87,7 @@ Here is how we could achieve the effect of the previous example using `Nested`:
```scala mdoc:silent
import cats.data.Nested
-import cats.implicits._
+import cats.syntax.all._
```
```scala mdoc
@@ -130,13 +108,13 @@ def even(i: Int): ErrorsOr[Int] = if (i % 2 == 0) i.validNel else s"$i is odd".i
nl.traverse(even)
```
-## Where are `Applicative`s for monad transformers?
+## Where are `Applicative`s for monad transformers?
-An `Applicative` instance for `OptionT[F, *]`/`EitherT[F, E, *]`, built without a corresponding `Monad` instance for `F`, would be unlawful, so it's not included. See [the guidelines](https://typelevel.org/cats/guidelines.html#applicative-monad-transformers) for a more detailed explanation.
+An `Applicative` instance for `OptionT[F, *]`/`EitherT[F, E, *]`, built without a corresponding `Monad` instance for `F`, would be unlawful, so it's not included. See [the guidelines](guidelines.md#applicative-instances-for-monad-transformers) for a more detailed explanation.
As an alternative, using `.toNested` on the monad transformer is recommended, although its `ap` will still be inconsistent with the Monad instance's.`.
-## Where is IO/Task?
+## Where is IO/Task?
In purely functional programming, a monadic `IO` or `Task` type is often used to handle side effects such as file/network IO. In some languages and frameworks, such a type also serves as the primary abstraction through which parallelism is achieved. Nearly every real-world purely functional application or service is going to require such a data type, and this gives rise to an obvious question: why doesn't Cats include such a type?
@@ -144,23 +122,17 @@ The answer is that Cats *does* include an `IO`, it just isn't included in the co
However, we acknowledge that this type may not meet everyone's needs. The cats-effect project characterizes the space of side-effect-capturing data types with a set of typeclasses (deriving from `cats.Monad`), and so all such data types are, broadly-speaking, mutually compatible and interchangeable in many generic contexts. For example, [Monix](https://monix.io) provides support for IO, concurrency, and streaming and integrates with the cats-effect type classes.
-It may be worth keeping in mind that `IO` and `Task` are pretty blunt instruments (they are essentially the `Any` of side effect management), and you may want to narrow the scope of your effects throughout most of your application. The [free monad]({{ site.baseurl }}/datatypes/freemonad.html) documentation describes a way to abstractly define controlled effects and interpret them into a type such as `IO` or `Task` as late as possible. As more of your code becomes pure through these controlled effects the less it matters which type you end up choosing to represent your side effects.
-
-## What does `@typeclass` mean?
-
-Cats defines and implements numerous type classes. Unfortunately, encoding these type classes in Scala can incur a large amount of boilerplate. To address this, [Simulacrum](https://github.com/typelevel/simulacrum) introduces `@typeclass`, a macro annotation which generates a lot of this boilerplate. This elevates type classes to a first class construct and increases the legibility and maintainability of the code. Use of simulacrum also ensures consistency in how the type classes are encoded across a project. Cats uses simulacrum wherever possible to encode type classes, and you can read more about it at the [project page](https://github.com/typelevel/simulacrum).
-
-Note that the one area where simulacrum is intentionally not used is in the `cats-kernel` module. The `cats-kernel` module is intended to be a shared dependency for a number of projects, and as such, it is important that it is both lightweight and very stable from a binary compatibility perspective. At some point there may be a transition from simulacrum to [typeclassic](https://github.com/typelevel/typeclassic), and the binary compatibility of moving between simulacrum and typeclassic is unclear at this point. Avoiding the dependency on simulacrum in `cats-kernel`, provides insulation against any potential binary compatibility problems in such a transition.
+It may be worth keeping in mind that `IO` and `Task` are pretty blunt instruments (they are essentially the `Any` of side effect management), and you may want to narrow the scope of your effects throughout most of your application. The [free monad](datatypes/freemonad.md) documentation describes a way to abstractly define controlled effects and interpret them into a type such as `IO` or `Task` as late as possible. As more of your code becomes pure through these controlled effects the less it matters which type you end up choosing to represent your side effects.
-## What do types like `?` and `λ` mean?
+## What do types like `?` and `λ` mean?
-Cats defines a wealth of type classes and type class instances. For a number of the type class and instance combinations, there is a mismatch between the type parameter requirements of the type class and the type parameter requirements of the data type for which the instance is being defined. For example, the [Either]({{ site.baseurl }}/datatypes/either.html) data type is a type constructor with two type parameters. We would like to be able to define a [Monad]({{ site.baseurl }}/typeclasses/monad.html) for `Either`, but the `Monad` type class operates on type constructors having only one type parameter.
+Cats defines a wealth of type classes and type class instances. For a number of the type class and instance combinations, there is a mismatch between the type parameter requirements of the type class and the type parameter requirements of the data type for which the instance is being defined. For example, the `Either` data type is a type constructor with two type parameters. We would like to be able to define a [Monad](typeclasses/monad.md) for `Either`, but the `Monad` type class operates on type constructors having only one type parameter.
-**Enter type lambdas!** Type lambdas provide a mechanism to allow one or more of the type parameters for a particular type constructor to be fixed. In the case of `Either` then, when defining a `Monad` for `Either`, we want to fix one of the type parameters at the point where a `Monad` instance is summoned, so that the type parameters line up. As `Either` is right biased, a type lambda can be used to fix the left type parameter and allow the right type parameter to continue to vary when `Either` is treated as a `Monad`. The right biased nature of `Either` is discussed further in the [`Either` documentation]({{ site.baseurl }}/datatypes/either.html).
+**Enter type lambdas!** Type lambdas provide a mechanism to allow one or more of the type parameters for a particular type constructor to be fixed. In the case of `Either` then, when defining a `Monad` for `Either`, we want to fix one of the type parameters at the point where a `Monad` instance is summoned, so that the type parameters line up. As `Either` is right biased, a type lambda can be used to fix the left type parameter and allow the right type parameter to continue to vary when `Either` is treated as a `Monad`.
**Enter [kind-projector](https://github.com/typelevel/kind-projector)!** kind-projector is a compiler plugin which provides a convenient syntax for dealing with type lambdas. The symbols `?` and `λ` are treated specially by kind-projector, and expanded into the more verbose definitions that would be required were it not to be used. You can read more about kind-projector at the [project page](https://github.com/typelevel/kind-projector).
-## What is `tailRecM`?
+## What is `tailRecM`?
The `FlatMap` type class has a `tailRecM` method with the following signature:
@@ -215,13 +187,13 @@ If you're having trouble figuring out how to implement `tailRecM` lawfully, you
In some cases you may decide that providing a lawful `tailRecM` may be impractical or even impossible (if so we'd like to hear about it). For these cases we provide a way of testing all of the monad laws _except_ for the stack safety of `tailRecM`: just replace `MonadTests[F].monad[A, B, C]` in your tests with `MonadTests[F].stackUnsafeMonad[A, B, C]`.
-## What does this symbol mean?
+## What does this symbol mean?
Below is a list of symbols used in Cats.
The `~>`, `⊥`, `⊤`, `:<:` and `:≺:` symbols can be imported with `import cats._`.
-All other symbols can be imported with `import cats.implicits._`
+All other symbols can be imported with `import cats.syntax.all._`
| Symbol | Name | Nickname | Type Class | Signature |
| -------------------------------- | -------------------------| ---------------- | ----------------------- | --------------------------------------------------------------------|
@@ -239,7 +211,7 @@ All other symbols can be imported with `import cats.implicits._`
| x |+| y | Semigroup combine | | `Semigroup[A]` | `combine(x: A, y: A): A` |
| `x <+> y` | SemigroupK combine | | `SemigroupK[F[_]]` | `combineK(x: F[A], y: F[A]): F[A]` |
| `f <<< g` | Arrow compose | | `Compose[F[_, _]]` | `compose(f: F[B, C], g: F[A, B]): F[A, C]` |
-| `f >>> g` | Arrow andThen | | `Compose[F[_, _]]` | `andThen(f: F[B, C], g: F[A, B]): F[A, C]` |
+| `f >>> g` | Arrow andThen | | `Compose[F[_, _]]` | `andThen(f: F[A, B], g: F[B, C]): F[A, C]` |
| `f &&& g` | Arrow merge | | `Arrow[F[_, _]]` | `merge[A, B, C](f: F[A, B], g: F[A, C]): F[A, (B, C)]` |
| `f -< g` | Arrow combine and bypass | | `Arrow[F[_, _]]` | `combineAndByPass[A, B, C](f: F[A, B], g: F[B, C]): F[A, (B, C)]` |
| `F ~> G` | natural transformation | | `FunctionK[F[_], G[_]]` | `FunctionK` alias |
@@ -252,20 +224,20 @@ All other symbols can be imported with `import cats.implicits._`
| `fa << fb` (Deprecated) | product left | | `FlatMap[F[_]]` | `productL(fa: F[A])(fb: F[B]): F[A]` |
-## How can I test instances against their type classes' laws?
+## How can I test instances against their type classes' laws?
-You can find more information [here](typeclasses/lawtesting.html).
+You can find more information [here](typeclasses/lawtesting.md).
-## How can I help?
+## How can I help?
The Сats community welcomes and encourages contributions, even if you are completely new to Сats and functional programming. Here are a few ways to help out:
- Find an undocumented method and write a ScalaDoc entry for it. See [Arrow.scala](https://github.com/typelevel/cats/blob/main/core/src/main/scala/cats/arrow/Arrow.scala) for some examples of ScalaDoc entries that use [sbt-doctest](https://github.com/tkawachi/sbt-doctest).
- Find an [open issue](https://github.com/typelevel/cats/issues?q=is%3Aopen+is%3Aissue+label%3Aready), leave a comment on it to let people know you are working on it, and submit a pull request. If you are new to Сats, you may want to look for items with the [low-hanging-fruit](https://github.com/typelevel/cats/issues?q=is%3Aopen+is%3Aissue+label%3A%22low-hanging+fruit%22) label.
-See the [contributing guide]({{ site.baseurl }}/contributing.html) for more information.
+See the [contributing guide](CONTRIBUTING.md) for more information.
-## How to try Cats in a REPL?
+## How to try Cats in a REPL?
The easiest way is probably using [Ammonite-REPL](http://ammonite.io/). Install it following the instructions there. Then in the amm console you can type in
```scala
@@ -274,6 +246,6 @@ import $ivy.`org.typelevel::cats-core:2.1.1`, cats._, cats.data._, cats.implicit
```
Or if you want, you can add these lines to `~/.ammonite/predef.sc` so that they are enabled every ammonite session.
-## Why aren't monad transformers like `OptionT` and `EitherT` covariant like `Option` and `Either`?
+## Why aren't monad transformers like `OptionT` and `EitherT` covariant like `Option` and `Either`?
Please see [Variance of Monad Transformers](https://typelevel.org/blog/2018/09/29/monad-transformer-variance.html) on the Typelevel blog.
diff --git a/docs/src/main/mdoc/guidelines.md b/docs/guidelines.md
similarity index 89%
rename from docs/src/main/mdoc/guidelines.md
rename to docs/guidelines.md
index baf5a5a05f..0a731cfc76 100644
--- a/docs/src/main/mdoc/guidelines.md
+++ b/docs/guidelines.md
@@ -1,36 +1,29 @@
----
-layout: page
-title: "Guidelines"
-section: "guidelines"
-position: 70
----
-
# Guidelines
All guidelines in Сats should have clear justifications. There is no room for tribal wisdom in a simple library.
## Syntax
-### Composing Implicit Conversions in Traits
+### Composing Implicit Conversions in Traits
Implicit syntax conversions provided in publicly-exposed traits should be marked final
so that any composition of the traits provides conversions that can all be inlined.
-### Ops Classes
+### Ops Classes
Ops classes should be marked final and extend AnyVal, to take full advantage of inlining and prevent unnecessary allocations.
The most notable exception is the case where all of the ops in the class are provided by zero-cost macros anyway,
for example with Simulacrum.
-### Partially-Applied Type
+### Partially-Applied Type
In Scala, when there are multiple type parameters in a function, either scalac infers all type parameters or the user has to
specify all of them. Often we have functions where there are one or more types that are inferable but not all of them. For example, there is helper function in `OptionT` that creates an `OptionT[F, A]` from an `A`. It could be written as:
```scala mdoc:silent
import cats._
-import cats.implicits._
+import cats.syntax.all._
import cats.data.OptionT
```
```scala mdoc
@@ -69,7 +62,7 @@ The user doesn't need to specify the type `A` which is given by the parameter.
You probably noticed that there is a `val dummy: Boolean` in the `PurePartiallyApplied` class. This is a trick we used
to make this intermediate class a [Value Class](http://docs.scala-lang.org/overviews/core/value-classes.html) so that there is no cost of allocation, i.e. at runtime, it doesn't create an instance of `PurePartiallyApplied`. We also hide this partially applied class by making it package private and placing it inside an object.
-### Implicit naming
+### Implicit naming
In a widely-used library it's important to minimize the chance that the names of implicits will be used by others and
therefore name our implicits according to the following rules:
@@ -86,17 +79,17 @@ This rule is relatively flexible. Use what you see appropriate. The goal is to m
-### Implicit instance priority
+### Implicit instance priority
When there are multiple instances provided implicitly, if the type class of them are in the same inheritance hierarchy,
the instances need to be separated out into different abstract class/traits so that they don't conflict with each other. The names of these abstract classes/traits should be numbered with a priority with 0 being the highest priority. The abstract classes/trait
with higher priority inherits from the ones with lower priority. The most specific (whose type class is the lowest in the hierarchy) instance should be placed in the abstract class/ trait with the highest priority. Here is an example.
```scala
-@typeclass
+
trait Functor[F[_]]
-@typeclass
+
trait Monad[F[_]] extends Functor
...
@@ -116,7 +109,7 @@ abstract class KleisliInstance1 {
We can introduce new type classes for the sake of adding laws that don't apply to the parent type class, e.g. `CommutativeSemigroup` and
`CommutativeArrow`.
-### Applicative instances for monad transformers
+### Applicative instances for monad transformers
We explicitly don't provide an instance of `Applicative` for e.g. `EitherT[F, String, *]` given an `Applicative[F]`.
An attempt to construct one without a proper `Monad[F]` instance would be inconsistent in `ap` with the provided `Monad` instance
diff --git a/docs/src/main/resources/microsite/img/cats-badge-big.png b/docs/img/cats-badge-big.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/cats-badge-big.png
rename to docs/img/cats-badge-big.png
diff --git a/docs/src/main/resources/microsite/img/cats-badge-normal.png b/docs/img/cats-badge-normal.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/cats-badge-normal.png
rename to docs/img/cats-badge-normal.png
diff --git a/docs/src/main/resources/microsite/img/cats-badge-tiny.png b/docs/img/cats-badge-tiny.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/cats-badge-tiny.png
rename to docs/img/cats-badge-tiny.png
diff --git a/docs/src/main/resources/microsite/img/cats-badge.svg b/docs/img/cats-badge.svg
similarity index 100%
rename from docs/src/main/resources/microsite/img/cats-badge.svg
rename to docs/img/cats-badge.svg
diff --git a/docs/src/main/resources/microsite/img/cats-logo.png b/docs/img/cats-logo.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/cats-logo.png
rename to docs/img/cats-logo.png
diff --git a/docs/src/main/resources/microsite/img/cats-logo.svg b/docs/img/cats-logo.svg
similarity index 100%
rename from docs/src/main/resources/microsite/img/cats-logo.svg
rename to docs/img/cats-logo.svg
diff --git a/docs/src/main/resources/microsite/img/cats2.png b/docs/img/cats2.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/cats2.png
rename to docs/img/cats2.png
diff --git a/docs/src/main/resources/microsite/img/donate-button.png b/docs/img/donate-button.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/donate-button.png
rename to docs/img/donate-button.png
diff --git a/docs/src/main/resources/microsite/img/favicon.png b/docs/img/favicon.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/favicon.png
rename to docs/img/favicon.png
diff --git a/docs/src/main/resources/microsite/img/jumbotron_pattern.png b/docs/img/jumbotron_pattern.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/jumbotron_pattern.png
rename to docs/img/jumbotron_pattern.png
diff --git a/docs/src/main/resources/microsite/img/jumbotron_pattern2x.png b/docs/img/jumbotron_pattern2x.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/jumbotron_pattern2x.png
rename to docs/img/jumbotron_pattern2x.png
diff --git a/docs/src/main/resources/microsite/img/missing-avatar.svg b/docs/img/missing-avatar.svg
similarity index 100%
rename from docs/src/main/resources/microsite/img/missing-avatar.svg
rename to docs/img/missing-avatar.svg
diff --git a/docs/src/main/resources/microsite/img/navbar_brand.png b/docs/img/navbar_brand.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/navbar_brand.png
rename to docs/img/navbar_brand.png
diff --git a/docs/src/main/resources/microsite/img/navbar_brand2x.png b/docs/img/navbar_brand2x.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/navbar_brand2x.png
rename to docs/img/navbar_brand2x.png
diff --git a/docs/src/main/resources/microsite/img/parallel.png b/docs/img/parallel.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/parallel.png
rename to docs/img/parallel.png
diff --git a/docs/src/main/resources/microsite/img/poster.png b/docs/img/poster.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/poster.png
rename to docs/img/poster.png
diff --git a/docs/src/main/resources/microsite/img/sidebar_brand.png b/docs/img/sidebar_brand.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/sidebar_brand.png
rename to docs/img/sidebar_brand.png
diff --git a/docs/src/main/resources/microsite/img/sidebar_brand2x.png b/docs/img/sidebar_brand2x.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/sidebar_brand2x.png
rename to docs/img/sidebar_brand2x.png
diff --git a/docs/src/main/resources/microsite/img/sponsors/47_degree.png b/docs/img/sponsors/47_degree.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/sponsors/47_degree.png
rename to docs/img/sponsors/47_degree.png
diff --git a/docs/src/main/resources/microsite/img/sponsors/commercetools.png b/docs/img/sponsors/commercetools.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/sponsors/commercetools.png
rename to docs/img/sponsors/commercetools.png
diff --git a/docs/src/main/resources/microsite/img/sponsors/ebiznext.png b/docs/img/sponsors/ebiznext.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/sponsors/ebiznext.png
rename to docs/img/sponsors/ebiznext.png
diff --git a/docs/src/main/resources/microsite/img/sponsors/evolution_gaming_engineering.png b/docs/img/sponsors/evolution_gaming_engineering.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/sponsors/evolution_gaming_engineering.png
rename to docs/img/sponsors/evolution_gaming_engineering.png
diff --git a/docs/src/main/resources/microsite/img/sponsors/inner-product.png b/docs/img/sponsors/inner-product.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/sponsors/inner-product.png
rename to docs/img/sponsors/inner-product.png
diff --git a/docs/src/main/resources/microsite/img/sponsors/iterators.png b/docs/img/sponsors/iterators.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/sponsors/iterators.png
rename to docs/img/sponsors/iterators.png
diff --git a/docs/src/main/resources/microsite/img/sponsors/triplequote.png b/docs/img/sponsors/triplequote.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/sponsors/triplequote.png
rename to docs/img/sponsors/triplequote.png
diff --git a/docs/src/main/resources/microsite/img/sponsors/underscore.png b/docs/img/sponsors/underscore.png
similarity index 100%
rename from docs/src/main/resources/microsite/img/sponsors/underscore.png
rename to docs/img/sponsors/underscore.png
diff --git a/docs/src/main/mdoc/typeclasses/imports.md b/docs/imports.md
similarity index 72%
rename from docs/src/main/mdoc/typeclasses/imports.md
rename to docs/imports.md
index ef13e73078..866a9986e1 100644
--- a/docs/src/main/mdoc/typeclasses/imports.md
+++ b/docs/imports.md
@@ -1,8 +1,3 @@
----
-layout: docs
-title: "Imports"
-section: "imports"
----
# Imports
The easiest approach to Сats imports is to import everything that's commonly needed:
@@ -13,7 +8,7 @@ import cats.data._
import cats.syntax.all._
```
-The `cats._` import brings in quite a few [type classes](http://typelevel.org/cats/typeclasses.html) (similar to interfaces) such as [Monad](http://typelevel.org/cats/typeclasses/monad.html), [Semigroup](http://typelevel.org/cats/typeclasses/semigroup.html), and [Foldable](http://typelevel.org/cats/typeclasses/foldable.html). Instead of the entire `cats` package, you can import only the types that you need, for example:
+The `cats._` import brings in quite a few [type classes](typeclasses.md) (similar to interfaces) such as [Monad](typeclasses/monad.md), [Semigroup](typeclasses/semigroup.md), and [Foldable](typeclasses/foldable.md). Instead of the entire `cats` package, you can import only the types that you need, for example:
```scala mdoc:reset:silent
import cats.Monad
@@ -21,7 +16,7 @@ import cats.Semigroup
import cats.Foldable
```
-The `cats.data._`, import brings in data structures such as [Validated](http://typelevel.org/cats/datatypes/validated.html) and [State](http://typelevel.org/cats/datatypes/state.html). Instead of the entire `cats.data` package, you can import only the types that you need, for example:
+The `cats.data._`, import brings in data structures such as [Validated](datatypes/validated.md) and [State](datatypes/state.md). Instead of the entire `cats.data` package, you can import only the types that you need, for example:
```scala mdoc:reset:silent
import cats.data.Validated
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000000..8cbf838018
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,206 @@
+# Cats
+
+
+
+[](https://index.scala-lang.org/typelevel/cats/cats-core) 
+[](https://opencollective.com/typelevel)
+[](https://discord.gg/XF3CXcMzqD)
+
+### Overview
+
+Cats is a library which provides abstractions for functional programming in the [Scala programming language](https://scala-lang.org).
+
+Scala supports both object-oriented and functional programming, and this is reflected in the hybrid approach of the
+standard library. Cats strives to provide functional programming abstractions that are core, [binary compatible](#binary-compatibility-and-versioning), [modular](https://typelevel.org/cats/motivations.html#modularity), [approachable](https://typelevel.org/cats/motivations.html#approachability) and [efficient](https://typelevel.org/cats/motivations.html#efficiency). A broader goal of Cats is to provide a foundation for an [ecosystem of pure, typeful libraries](https://typelevel.org/cats/typelevelEcosystem.html) to support functional programming in Scala applications.
+
+For more detail about Cats' motivations, go [here](https://typelevel.org/cats/motivations.html).
+
+### Why "cats"?
+
+The name is a playful shortening of the word *category*, from "[category theory](https://en.wikipedia.org/wiki/Category_theory)".
+
+Regardless, you do not need to know anything about category theory to use Cats.
+
+## Contributors
+
+### Code Contributors
+
+This project exists thanks to [all the people who contribute](https://github.com/typelevel/cats/graphs/contributors). We welcome contributions to Cats and would love for you to help build
+Cats. See our [contributor guide](CONTRIBUTING.md) for more
+information about how you can get involved as a developer. If you are looking for something to start with, [here is a beginner friendly list](https://github.com/typelevel/cats/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
+
+### Financial Contributors
+
+[Become a financial contributor](https://opencollective.com/typelevel) and help us sustain our community. Donations directly support office hours for maintainers, better documentation and strategic initiatives.
+
+Platinum Sponsors
+Platinum sponsorship starts at $950 USD/month.
+
+
+Gold Sponsors
+Gold Sponsorship starts at $420 USD/month.
+
+
+Silver Sponsors
+Silver Sponsorship starts at $180 USD/month.
+
+
+Backers
+Become a Backer with a recurring donation of just $5 USD/month.
+
+
+Other contributors
+We thankfully accept one-time and recurring contributions as well.
+
+
+
+
+### Getting Started
+
+Cats is available for [Scala.js](http://www.scala-js.org/) and [Scala Native](https://www.scala-native.org/), as well as the standard JVM runtime.
+
+Cats relies on improved type inference via the fix for [SI-2712](https://github.com/scala/bug/issues/2712), which is not enabled by default. For **Scala 2.12** you should add the following to your `build.sbt`:
+
+```scala
+scalacOptions += "-Ypartial-unification"
+```
+
+(Partial unification is on by default since Scala 2.13, the compiler no longer accepts `-Ypartial-unification`)
+
+And then create the Cats dependency, by adding the following to your `build.sbt`:
+
+```scala
+libraryDependencies += "org.typelevel" %% "cats-core" % "@VERSION@"
+```
+
+This will pull in the cats-core module. If you require some other
+functionality, you can pick-and-choose from amongst these modules
+(used in place of `"cats-core"`):
+
+* `cats-kernel`: Small set of basic type classes (*required*).
+* `cats-core`: Most core type classes and functionality (*required*).
+* `cats-laws`: Laws for testing type class instances.
+* `cats-free`: Free structures such as the free monad, and supporting type classes.
+* `cats-testkit`: lib for writing tests for type class instances using laws.
+* `algebra`: Type classes to represent algebraic structures.
+* `alleycats-core`: Cats instances and classes which are not lawful.
+
+There are several other Cats modules that are in separate repos so that they can
+maintain independent release cycles.
+
+* [`cats-effect`](https://github.com/typelevel/cats-effect): standard `IO` type together with `Sync`, `Async` and `Effect` type classes
+* [`cats-mtl`](https://github.com/typelevel/cats-mtl): transformer typeclasses for Cats' Monads, Applicatives and Functors.
+* [`mouse`](https://github.com/typelevel/mouse): a small companion to Cats that provides convenient syntax (aka extension methods)
+* [`kittens`](https://github.com/typelevel/kittens): automatic type class instance derivation for Cats and generic utility functions
+* [`cats-tagless`](https://github.com/typelevel/cats-tagless): Utilities for tagless final encoded algebras
+* [`cats-collections`](https://github.com/typelevel/cats-collections): Data structures which facilitate pure functional programming
+* [`cats-testkit-scalatest`](https://github.com/typelevel/cats-testkit-scalatest): Cats testkit integration with Scalatest
+
+Past release notes for Cats are available in [CHANGES.md](https://github.com/typelevel/cats/blob/main/CHANGES.md).
+
+### Community
+
+Discussion around Cats is currently happening on GitHub issues, PR pages,
+and Discord:
+
+The [Typelevel Discord](https://discord.gg/XF3CXcMzqD) has \#cats and \#cats-dev
+channels, as well as community channels such as \#beginners. Please join us!
+
+People are expected to follow the
+[Scala Code of Conduct](https://www.scala-lang.org/conduct/) when
+discussing Cats on GitHub, Discord, or other venues.
+
+We hope that our community will be respectful, helpful, and kind. If
+you find yourself embroiled in a situation that becomes heated, or
+that fails to live up to our expectations, you should disengage and
+contact one of the [project maintainers](#maintainers) in private. We
+hope to avoid letting minor aggressions and misunderstandings escalate
+into larger problems.
+
+If you are being harassed, please contact one of [us](#maintainers)
+immediately so that we can support you.
+
+### Binary compatibility and versioning
+
+After `1.0.0` release, we [decided](https://github.com/typelevel/cats/issues/1233)
+to use *MAJOR.MINOR.PATCH* [Semantic Versioning 2.0.0](http://semver.org/)
+going forward, which is different from the *EPOCH.MAJOR.MINOR* scheme common among
+Java and Scala libraries (including the Scala lang).
+
+Cats strives to provide a solid and stable foundation for an ecosystem of
+FP libraries. Thus, we treat backward binary compatibility maintenance with a high priority.
+In semantic versioning, backward breaking change is **ONLY** allowed between *MAJOR* versions.
+We will maintain backward binary compatibility between *PATCH* AND *MINOR* versions.
+For example, when we release Cats `1.1.0`, it will be backward binary compatible
+with the previous `1.0.x` versions. I.E. the new JAR will be a drop-in replacement for
+the old one. This is critical when your application has a diamond
+dependency on Cats - depending on two or more libraries that all depend on Cats.
+If one library upgrades to the new `1.1.0` Cats before the other one does, your
+application still runs thanks to this backward binary compatibility.
+
+Also worth noting is that according to semantic versioning,
+*MINOR* version Y (x.Y.z | x > 0) MUST be incremented
+if new, backwards compatible functionality is introduced to the public API.
+It MUST be incremented if any public API functionality is marked as deprecated.
+
+Any binary breaking changes will require a *MAJOR* version bump, which we will be very
+cautious about. We will also consider using `organization` and package name for major
+versioning in the future. But that decision is yet to be made.
+
+### Adopters
+
+A (non-exhaustive) list of companies that use Cats in production is featured on the [Adopters page]. Don't see yours? [You can add it in a PR!](https://github.com/typelevel/cats/edit/main/ADOPTERS.md) And if you can, consider [supporting us](https://opencollective.com/typelevel).
+
+### Maintainers
+
+The current maintainers (people who can merge pull requests) are:
+
+* [rossabaker](https://github.com/rossabaker) Ross Baker
+* [armanbilge](https://github.com/armanbilge) Arman Bilge
+* [johnynek](https://github.com/johnynek) P. Oscar Boykin
+* [adelbertc](https://github.com/adelbertc) Adelbert Chang
+* [danicheg](https://github.com/danicheg) Daniel Esik
+* [LukaJCB](https://github.com/LukaJCB) Luka Jacobowitz
+* [peterneyens](https://github.com/peterneyens) Peter Neyens
+* [tpolecat](https://github.com/tpolecat) Rob Norris
+* [non](https://github.com/non) Erik Osheim
+* [barambani](https://github.com/barambani) Filippo Mariotti
+* [mpilquist](https://github.com/mpilquist) Michael Pilquist
+* [milessabin](https://github.com/milessabin) Miles Sabin
+* [djspiewak](https://github.com/djspiewak) Daniel Spiewak
+* [fthomas](https://github.com/fthomas) Frank Thomas
+* [satorg](https://github.com/satorg) Sergey Torgashov
+* [julien-truffaut](https://github.com/julien-truffaut) Julien Truffaut
+* [kailuowang](https://github.com/kailuowang) Kailuo Wang
+
+Retired committers include:
+
+* [ceedubs](https://github.com/ceedubs) Cody Allen
+* [travisbrown](https://github.com/travisbrown) Travis Brown
+
+We are currently following a practice of requiring at least two
+sign-offs to merge code PRs (and for large or contentious issues we may
+wait for more). For typos, documentation improvements or minor build fix we
+relax this to a single sign-off. More detail in the [process document](https://github.com/typelevel/cats/blob/main/PROCESS.md).
+
+
+### Copyright and License
+
+All code is available to you under the MIT license, available at
+http://opensource.org/licenses/mit-license.php and also in the
+[COPYING](https://github.com/typelevel/cats/blob/main/COPYING) file. The design is informed by many other
+projects, in particular [Scalaz](https://github.com/scalaz/scalaz).
+
+Copyright the maintainers, 2015-2024.
+
+[Adopters page]: ADOPTERS.md
\ No newline at end of file
diff --git a/docs/src/main/resources/microsite/js/sponsors.js b/docs/js/sponsors.js
similarity index 82%
rename from docs/src/main/resources/microsite/js/sponsors.js
rename to docs/js/sponsors.js
index 13daa94360..fd22d9ad62 100644
--- a/docs/src/main/resources/microsite/js/sponsors.js
+++ b/docs/js/sponsors.js
@@ -38,11 +38,11 @@ var sponsors = async function () {
for (i = 0; i < members.length; i++) {
var member = members[i];
switch (member.tier ? member.tier.name : null) {
- case 'platinum-sponsor':
+ case 'Platinum Sponsor':
addSponsor('platinum-sponsors', member.account, PlatinumSize);
- case 'gold-sponsor':
+ case 'Gold Sponsor':
addSponsor('gold-sponsors', member.account, GoldSize);
- case 'silver-sponsor':
+ case 'Silver Sponsor':
addSponsor('silver-sponsors', member.account, SilverSize);
case 'backer':
addSponsor('backers', member.account, BackerSize);
@@ -60,39 +60,39 @@ sponsors();
addSponsor('gold-sponsors', {
name: "47 Degrees",
website: "https://47deg.com",
- imageUrl: "https://typelevel.org/cats/img/sponsors/47_degree.png"
+ imageUrl: "img/sponsors/47_degree.png"
});
addSponsor('gold-sponsors', {
name: "Iterators",
website: "https://iteratorshq.com",
- imageUrl: "https://typelevel.org/cats/img/sponsors/iterators.png",
+ imageUrl: "img/sponsors/iterators.png",
marginBottom: 20
});
addSponsor('gold-sponsors', {
name: "Triplequote",
website: "https://triplequote.com",
- imageUrl: "https://typelevel.org/cats/img/sponsors/triplequote.png",
+ imageUrl: "img/sponsors/triplequote.png",
marginBottom: 20
});
addSponsor('gold-sponsors', {
name: "Underscore",
website: "https://underscore.com",
- imageUrl: "https://typelevel.org/cats/img/sponsors/underscore.png",
+ imageUrl: "img/sponsors/underscore.png",
marginBottom: 10
});
addSponsor('silver-sponsors', {
name: "Ebiznext",
website: "https://ebiznext.com",
- imageUrl: "https://typelevel.org/cats/img/sponsors/ebiznext.png",
+ imageUrl: "img/sponsors/ebiznext.png",
marginBottom: 10
});
addSponsor('silver-sponsors', {
name: "Inner Product",
website: "https://inner-product.com",
- imageUrl: "https://typelevel.org/cats/img/sponsors/inner-product.png"
+ imageUrl: "img/sponsors/inner-product.png"
});
addSponsor('silver-sponsors', {
name: "Evolution Gaming Engineering",
website: "https://evolutiongaming.com",
- imageUrl: "https://typelevel.org/cats/img/sponsors/evolution_gaming_engineering.png"
+ imageUrl: "img/sponsors/evolution_gaming_engineering.png"
});
diff --git a/docs/src/main/mdoc/jump_start_guide.md b/docs/jump_start_guide.md
similarity index 94%
rename from docs/src/main/mdoc/jump_start_guide.md
rename to docs/jump_start_guide.md
index a00c8aed35..52cdf09747 100644
--- a/docs/src/main/mdoc/jump_start_guide.md
+++ b/docs/jump_start_guide.md
@@ -1,8 +1,4 @@
----
-layout: page
-title: "Jump Start Guide"
-section: "jump_start_guide"
----
+{% laika.title = Jump Start Guide %}
# Introduction
@@ -18,9 +14,11 @@ We are sticking to [version 1.0.1](https://github.com/typelevel/cats/releases/ta
Let's go through the library package-wise, looking at the syntax available in each package.
-# Helpers for `Option` and `Either`
+# Option Helpers
-## `import cats.syntax.all._`
+```scala mdoc:silent
+import cats.syntax.all._
+```
Importing this package enables `obj.some` syntax — equivalent to `Some(obj)`.
The only real difference is that the value is already upcast to `Option[T]` from `Some[T]`.
@@ -39,8 +37,6 @@ implicit class ToFutureSuccessful[T](obj: T) {
then you can use the chained syntax shown below:
```scala mdoc:silent
-import cats.syntax.all._
-
class Account { /* ... */ }
trait AccountService {
@@ -64,15 +60,17 @@ Chaining `.some.asFuture` at the end rather than putting it at the front also he
Providing a more specialized type sometimes helps the Scala compiler properly infer the type of expressions containing `None`.
-## `import cats.syntax.all._`
+# Either Helpers
+
+```scala mdoc:silent
+import cats.syntax.all._
+```
`obj.asRight` is `Right(obj)`, `obj.asLeft` is `Left(obj)`.
In both cases the type of returned value is widened from `Right` or `Left` to `Either`.
Just as was the case with `.some`, these helpers are handy to combine with `.asFuture` to improve readability:
```scala mdoc:silent
-import cats.syntax.all._
-
case class User(accountId: Long) { /* ... */ }
trait UserService {
@@ -94,7 +92,7 @@ If the provided `option` is `Some(x)`, it becomes `Right(x)`.
Otherwise it becomes `Left` with the provided `ifNone` value inside.
-## `import cats.syntax.all._`
+# Tuples
The `apply` package provides `(..., ..., ...).mapN` syntax, which allows for an intuitive construct for applying a function that takes more than one parameter to multiple effectful values (like futures).
@@ -126,8 +124,8 @@ def processAsync: Future[ProcessingResult] = {
}
```
-By default the implicit instances (namely, [`Functor[Future]`](http://typelevel.org/cats/api/cats/Functor.html) and
-[`Semigroupal[Future]`](https://typelevel.org/cats/api/cats/Semigroupal.html)) required for `mapN` to work properly are always visible. They are present in the respective companion objects of the instances and hence we do not need to import them explicitly.
+By default the implicit instances (namely, [`Functor[Future]`](@API_URL@/cats/Functor.html) and
+[`Semigroupal[Future]`](@API_URL@/cats/Semigroupal.html)) required for `mapN` to work properly are always visible. They are present in the respective companion objects of the instances and hence we do not need to import them explicitly.
This above idea can be expressed even shorter, just:
@@ -157,9 +155,11 @@ But since the computations are independent of one another, it's perfectly viable
# Traversing
-## ```import cats.syntax.all._```
+```scala mdoc:silent
+import cats.syntax.all._
+```
-### `traverse`
+## `traverse`
If you have an instance `obj` of type `F[A]` that can be mapped over (like `Future`) and a function `fun` of type `A => G[B]`, then calling `obj.map(fun)` would give you `F[G[B]]`.
In many common real-life cases, like when `F` is `Option` and `G` is `Future`, you would get `Option[Future[B]]`, which most likely isn't what you wanted.
@@ -168,8 +168,6 @@ In many common real-life cases, like when `F` is `Option` and `G` is `Future`, y
If you call `traverse` instead of `map`, like `obj.traverse(fun)`, you'll get `G[F[A]]`, which will be `Future[Option[B]]` in our case; this is much more useful and easier to process than `Option[Future[B]]`.
```scala mdoc:silent
-import cats.syntax.all._
-
def updateUser(user: User): Future[User] = { /* ... */ ??? }
def updateUsers(users: List[User]): Future[List[User]] = {
@@ -180,13 +178,11 @@ def updateUsers(users: List[User]): Future[List[User]] = {
As a side note, there is also a dedicated method `Future.traverse` in the [`Future`](http://www.scala-lang.org/api/current/scala/concurrent/Future$.html) companion object,
but the Cats version is far more readable and can easily work on any structure for which certain type classes are available.
-### `sequence`
+## `sequence`
`sequence` represents an even simpler concept: it can be thought of as simply swapping the types from `F[G[A]]` to `G[F[A]]` without even mapping the enclosed value like `traverse` does.
```scala mdoc:silent
-import cats.syntax.all._
-
val foo: List[Future[String]] = List(Future("hello"), Future("world"))
val bar = foo.sequence // will have Future[List[String]] type
```
@@ -195,7 +191,7 @@ val bar = foo.sequence // will have Future[List[String]] type
On the other hand, `obj.traverse(fun)` is roughly equivalent to `obj.map(fun).sequence`.
-### `flatTraverse`
+## `flatTraverse`
If you have an `obj` of type `F[A]` and a function `fun` of type `A => G[F[B]]`, then doing `obj.map(f)` yields result of type `F[G[F[B]]]` — very unlikely to be what you wanted.
@@ -203,8 +199,6 @@ Traversing the `obj` instead of mapping helps a little — you'll get `G[F[F[B]]
Since `G` is usually something like `Future` and `F` is `List` or `Option`, you would end up with `Future[Option[Option[A]]` or `Future[List[List[A]]]` — a bit awkward to process.
```scala mdoc:silent
-import cats.syntax.all._
-
lazy val valueOpt: Option[Int] = { /* ... */ ??? }
def compute(value: Int): Future[Option[Int]] = { /* ... */ ??? }
def computeOverValue: Future[Option[Option[Int]]] = valueOpt.traverse(compute) // has type Future[Option[Option[Int]]], not good
@@ -223,12 +217,15 @@ def computeOverValue3: Future[Option[Int]] = valueOpt.flatTraverse(compute)
and that solves our problem for good.
+# Monad Transformers
-# Monad transformers
+## OptionT
-## `import cats.data.OptionT`
+```scala mdoc:silent
+import cats.data.OptionT
+```
-An instance of [`OptionT[F, A]`](http://typelevel.org/cats/api/cats/data/EitherT.html) can be thought of as a wrapper over `F[Option[A]]`
+An instance of [`OptionT[F, A]`](datatypes/optiont.md) can be thought of as a wrapper over `F[Option[A]]`
which adds a couple of useful methods specific to nested types that aren't available in `F` or `Option` itself.
Most typically, your `F` will be `Future` (or sometimes slick's `DBIO`, but this requires having an implementation of Cats type classes like `Functor` or `Monad` for `DBIO`).
Wrappers such as `OptionT` are generally known as _monad transformers_.
@@ -249,8 +246,6 @@ def mappedResultFuture: Future[Option[String]] = resultFuture.map { maybeValue =
With the use of `OptionT`, this can be simplified as follows:
```scala mdoc:silent
-import cats.data.OptionT
-
def mappedResultFuture2: OptionT[Future, String] = OptionT(resultFuture).map { value =>
// Do something with the value and return String
???
@@ -272,7 +267,7 @@ The method headers in the table below are slightly simplified: the type paramete
| `OptionT.liftF` | `F[A]` | `OptionT[F, A]` |
| `OptionT.pure` | `A` | `OptionT[F, A]` |
-In production code you'll most commonly use the `OptionT(...)` syntax in order to wrap an instance of `Future[Option[A]]` into `Option[F, A]`.
+In production code you'll most commonly use the `OptionT(...)` syntax in order to wrap an instance of `Future[Option[A]]` into `OptionT[F, A]`.
The other methods, in turn, prove useful to set up `OptionT`-typed dummy values in unit tests.
We have already come across one of `OptionT`'s methods, namely `map`.
@@ -292,8 +287,6 @@ In practice, you're most likely to use `map` and `semiflatMap`.
As is always the case with `flatMap` and `map`, you can use it not only explicitly, but also under the hood in `for` comprehensions, as in the example below:
```scala mdoc:silent
-import cats.data.OptionT
-
class Money { /* ... */ }
def findUserById(userId: Long): OptionT[Future, User] = { /* ... */ ??? }
@@ -313,9 +306,13 @@ The `OptionT[Future, Money]` instance returned by `getReservedFundsForUser` will
Otherwise, if the result of all three calls contains `Some`, the final outcome will also contain `Some`.
-## `import cats.data.EitherT`
+## EitherT
+
+```scala mdoc:silent
+import cats.data.EitherT
+```
-[`EitherT[F, A, B]`](http://typelevel.org/cats/api/cats/data/EitherT.html) is the monad transformer for `Either` — you can think of it as a wrapper over a `F[Either[A, B]]` value.
+[`EitherT[F, A, B]`](datatypes/eithert.md) is the monad transformer for `Either` — you can think of it as a wrapper over a `F[Either[A, B]]` value.
Just as in the above section, I simplified the method headers, skipping type parameters or their context bounds and lower bounds.
@@ -332,8 +329,6 @@ Let's have a quick look at how to create an `EitherT` instance:
Another useful way to construct an `EitherT` instance is to use `OptionT`'s methods `toLeft` and `toRight`:
```scala mdoc:silent
-import cats.data.EitherT
-
abstract class BaseException(message: String) extends Exception(message)
case class UserNotFoundException(message: String) extends BaseException(message)
diff --git a/docs/src/main/mdoc/motivations.md b/docs/motivations.md
similarity index 86%
rename from docs/src/main/mdoc/motivations.md
rename to docs/motivations.md
index 3146fcc855..bab6174237 100644
--- a/docs/src/main/mdoc/motivations.md
+++ b/docs/motivations.md
@@ -1,10 +1,4 @@
----
-layout: page
-title: "Motivations"
-section: "motivations"
-position: 25
----
-
+{% laika.title = Motivations %}
#### Approachability
@@ -16,12 +10,12 @@ in trying to teach others about these concepts, and trying to make
decisions which will help ease the process of getting acquainted to
the library for a newcomer. If you have any feedback for us in this
regard, we would love to hear from you. See the [Contributing
-page](contributing.html) to find out ways to give us feedback.
+page](CONTRIBUTING.md) to find out ways to give us feedback.
#### Modularity
We are trying to make the library modular. It will have a tight
-core which will contain only the [type classes](typeclasses.html),
+core which will contain only the [type classes](typeclasses.md),
the bare minimum of data structures that are needed to support
them, and type class instances for those data structures and standard
library types.
@@ -37,7 +31,7 @@ how the software can be used.
Writing documentation is a huge part of developing software, and one
that is often neglected. It is also a very easy way to get started
-with [contributing](contributing.html) to the project.
+with [contributing](CONTRIBUTING.md) to the project.
#### Efficiency
diff --git a/docs/src/main/mdoc/nomenclature.md b/docs/nomenclature.md
similarity index 82%
rename from docs/src/main/mdoc/nomenclature.md
rename to docs/nomenclature.md
index d4c8f31a82..961b07fb14 100644
--- a/docs/src/main/mdoc/nomenclature.md
+++ b/docs/nomenclature.md
@@ -1,9 +1,4 @@
----
-layout: page
-title: "Glossary"
-section: "Glossary"
-position: 60
----
+# Glossary
This is a catalogue of the major functions, type classes, and data types in `Cats`. It serves as a bird's-eye view of each class capabilities. It is also intended as a go-to reference for `Cats` users, who may not recall the answer to questions like these:
@@ -19,16 +14,17 @@ _WARNING_: this page is written manually, and not automatically generated, so ma
### Functor
-| Type | Method Name |
-| ------------- |--------------|
-| `F[A] => F[Unit]` | `void` |
-| `F[A] => B => F[B]` | `as` |
-| `F[A] => (A => B) => F[B]` | `map` |
-| `F[A] => (A => B) => F[(A,B)]` | `fproduct` |
-| `F[A] => (A => B) => F[(B,A)]` | `fproductLeft` |
-| `F[A] => B => F[(B, A)]` | `tupleLeft` |
-| `F[A] => B => F[(A, B)]` | `tupleRight` |
-| `(A => B) => (F[A] => F[B])` | `lift` |
+| Type | Method Name | Notes |
+|--------------------------------|----------------|-------|
+| `F[A] => F[Unit]` | `void` |
+| `F[A] => B => F[B]` | `as` |
+| `F[A] => (A => B) => F[B]` | `map` |
+| `F[A] => (A => A1) => F[A1])` | `mapOrKeep` | A1 >: A, the (A => A1) is a PartialFunction
+| `F[A] => (A => B) => F[(A,B)]` | `fproduct` |
+| `F[A] => (A => B) => F[(B,A)]` | `fproductLeft` |
+| `F[A] => B => F[(B, A)]` | `tupleLeft` |
+| `F[A] => B => F[(A, B)]` | `tupleRight` |
+| `(A => B) => (F[A] => F[B])` | `lift` |
### Apply
@@ -115,14 +111,14 @@ Like the previous section, we use the `E` for the error parameter type.
| Type | Method Name | Constraints
| ------------- |--------------|-----------
| `F[A] => A` | `fold` | `A: Monoid`
-| `F[A] => B => ((B,A) => B) => F[B]` | `foldLeft`
+| `F[A] => B => ((B,A) => B) => B` | `foldLeft`
| `F[A] => (A => B) => B` | `foldMap` | `B: Monoid`
| `F[A] => (A => G[B]) => G[B]` | `foldMapM` | `G: Monad` and `B: Monoid`
| `F[A] => (A => B) => Option[B]` | `collectFirst` | The `A => B` is a `PartialFunction`
| `F[A] => (A => Option[B]) => Option[B]` | `collectFirstSome` |
| `F[A] => (A => G[B]) => G[Unit]` | `traverse_` | `G: Applicative`
| `F[G[A]] => G[Unit]` | `sequence_` | `G: Applicative`
-| `F[A] => (A => Either[B, C] => (F[B], F[C])` | `partitionEither` | `G: Applicative`
+| `F[A] => (A => Either[B, C]) => (F[B], F[C])` | `partitionEither` | `G: Applicative`
### Reducible
@@ -141,8 +137,38 @@ Like the previous section, we use the `E` for the error parameter type.
| `F[G[F[A]]] => G[F[A]]` | `flatSequence` | `G: Applicative` and `F: FlatMap`
| `F[A] => F[(A,Int)]` | `zipWithIndex` |
| `F[A] => ((A,Int) => B) => F[B]` | `mapWithIndex` |
-| `F[A] => ((A,Int) => G[B]) => G[F[B]]` | `traverseWithIndex` | `F: Monad`
+| `F[A] => ((A,Int) => G[B]) => G[F[B]]` | `traverseWithIndexM` | `F: Monad`
+
+### SemigroupK
+| Type | Method Name | Constraints |
+|------------|--------------|-----------|
+| `F[A] => F[A] => F[A]`| `combineK` |
+| `F[A] => Int => F[A]` | `combineNK`
+| `F[A] => F[B] => F[Either[A, B]]` | `sum` | `F: Functor`
+| `IterableOnce[F[A]] => Option[F[A]]` | `combineAllOptionK`
+
+### MonoidK
+| Type | Method Name | Constraints |
+|------------|--------------|-----------|
+| `F[A]` | `empty`
+| `F[A] => Boolean` | `isEmpty`
+| `IterableOnce[F[A]] => F[A]` | `combineAllK`
+### Alternative
+| Type | Method Name | Constraints |
+|------------|--------------|-----------|
+| `F[G[A]] => F[A]` | `unite` | `F: FlatMap` and `G: Foldable`
+| `F[G[A, B]] => (F[A], F[B])` | `separate` | `F: FlatMap` and `G: Bifoldable`
+| `F[G[A, B]] => (F[A], F[B])` | `separateFoldable` | `F: Foldable` and `G: Bifoldable`
+| `Boolean => F[Unit]` | `guard`
+| `IterableOnce[A] => F[A]` | `fromIterableOnce`
+| `G[A] => F[A]` | `fromFoldable` | `G: Foldable`
+
+### NonEmptyAlternative
+| Type | Method Name | Constraints |
+|------------|--------------|-----------|
+| `A => F[A] => F[A]` | `prependK`
+| `F[A] => A => F[A]` | `appendK`
## Transformers
@@ -171,13 +197,17 @@ For convenience, in these types we use the symbol `OT` to abbreviate `OptionT`.
| `=> OT[F, A]` | `none` | `F: Applicative` |
| `A => OT[F, A]` | `some` or `pure` | `F: Applicative`
| `F[A] => OT[F, A]` | `liftF` | `F: Functor`
+| `Boolean => F[A] => OT[F, A]` | `whenF` | `F: Applicative`
+| `F[Boolean] => F[A] => OT[F, A]` | `whenM` | `F: Monad`
| `OT[F, A] => F[Option[A]]` | `value`
+| `OT[F, A] => A => Boolean => OT[F, A]` | `filter` | `F: Functor`
+| `OT[F, A] => A => F[Boolean] => OT[F, A]` | `filterF` | `F: Monad`
| `OT[F, A] => (A => B) => OT[F, B]` | `map` | `F: Functor`
| `OT[F, A] => (F ~> G) => OT[G, B]` | `mapK`
| `OT[F, A] => (A => Option[B]) => OT[F, B]` | `mapFilter` | `F: Functor`
| `OT[F, A] => B => (A => B) => F[B]` | `fold` or `cata`
| `OT[F, A] => (A => OT[F, B]) => OT[F,B]` | `flatMap`
-| `OT[F, A] => (A => F[Option[B]]) => F[B]` | `flatMapF` | `F: Monad` |
+| `OT[F, A] => (A => F[Option[B]]) => OT[F,B]` | `flatMapF` | `F: Monad` |
| `OT[F, A] => A => F[A]` | `getOrElse` | `F: Functor` |
| `OT[F, A] => F[A] => F[A]` | `getOrElseF` | `F: Monad` |
| `OT[F, A] => OT[F, A] => OT[F, A]` |
@@ -254,7 +284,7 @@ Here, we use `Ki` as a short-hand for `Kleisli`.
| `F[A, B] => F[C, A] => F[C, B]` | `compose` | `<<<` |
| `F[A, B] => F[B, C] => F[A, C]` | `andThen` | `>>>` |
| `=> F[A,A]` | `id` |
-| `F[A, B] => F[C, B] => F[Either[A, C], B]` | `choice` | `|||`
+| `F[A, B] => F[C, B] => F[Either[A, C], B]` | `choice` | `|||` |
| `=> F[ Either[A, A], A]` | `codiagonal` |
#### Arrow
@@ -283,6 +313,6 @@ Because `Сats` is a Scala library and Scala has many knobs and switches, the ac
- For functions defined as method of the typeclass trait, we ignore the receiver object.
- We ignore implicit parameters that represent type-class constraints; and write them on a side column instead.
- We use `A => B` for both `Function1[A, B]` and `PartialFunction[A, B]` parameters, without distinction. We add a side note when one is a `PartialFunction`.
-- Some functions are defined through the [Partially Applied Type Params](http://typelevel.org/cats/guidelines.html#partially-applied-type-params) pattern. We ignore this.
+- Some functions are defined through the [Partially Applied Type Params](guidelines.md#partially-applied-type) pattern. We ignore this.
- We ignore the distinction between by-name and by-value input parameters. We use the notation `=> A`, without parameters, to indicate constant functions.
- We ignore Scala variance annotations. We also ignore extra type parameters, which in some methods are added with a subtype-constraint, (e.g. `B >: A`). These are usually meant for flexibility, but we replace each one by its bound.
diff --git a/docs/src/main/mdoc/resources_for_learners.md b/docs/resources_for_learners.md
similarity index 76%
rename from docs/src/main/mdoc/resources_for_learners.md
rename to docs/resources_for_learners.md
index d22c8340b8..ae47cf21d5 100644
--- a/docs/src/main/mdoc/resources_for_learners.md
+++ b/docs/resources_for_learners.md
@@ -1,12 +1,8 @@
----
-layout: page
-title: "Resources for Learners"
-section: "resources_for_learners"
-position: 30
----
+{% laika.title = Resources for Learners %}
+
# Books
- * [Functional Programming in Scala](https://www.manning.com/books/functional-programming-in-scala)
- by Paul Chiusano and Rúnar Bjarnason - While this book does not
+ * [Functional Programming in Scala](https://www.manning.com/books/functional-programming-in-scala-second-edition)
+ by Michael Pilquist, Rúnar Bjarnason, and Paul Chiusano - While this book does not
specifically cover Cats, it is a great introduction to functional
programming in Scala in general and covers some of the abstractions
that can be found in Cats.
@@ -31,11 +27,15 @@ position: 30
* [Functional Structures in Scala](https://www.youtube.com/playlist?list=PLFrwDVdSrYE6dy14XCmUtRAJuhCxuzJp0)
by [Michael Pilquist](https://github.com/MPilquist) offers a series
of lectures about basic functional structures.
- * [Category Theory for Programmers](https://www.youtube.com/playlist?list=PLbgaMIhjbmEnaH_LTkxLI7FMa2HsnawM_)
+ * **Category Theory for Programmers**
by [Bartosz Milewski](https://github.com/BartoszMilewski) is a series
- of category theory lectures oriented towards programmers. The sample code
- is in basic Haskell/C++ but the course is designed for programmers of all
- background to follow.
+ of category theory lectures oriented towards programmers.
+ The code examples are written in Haskell and C++,
+ but the course is designed for programmers of any background,
+ even the ones without a strong maths knowledge.
+ * [part 1](https://www.youtube.com/playlist?list=PLbgaMIhjbmEnaH_LTkxLI7FMa2HsnawM_)
+ * [part 2](https://www.youtube.com/playlist?list=PLbgaMIhjbmElia1eCEZNvsVscFef9m0dm)
+ * [part 3](https://www.youtube.com/playlist?list=PLbgaMIhjbmEn64WVX4B08B4h2rOtueWIL)
* [Easy and efficient data validation with Cats](https://www.youtube.com/watch?v=P8nGAo3Jp-Q) by [Daniela Sfregola](https://danielasfregola.com/) this talk introduces Cats, and some of its most interesting components for data validation. In particular, we’ll discuss some options to achieve efficient and expressive data validation. We will also argue that, compared to other options in the language, Cats is particularly suited for the task thanks to its easy-to-use data types and more approachable syntax.
* [Cats by example](https://www.youtube.com/playlist?list=PLy4hTMY6erDBmvZiEDjtCTP8XCdhaXc2c) by [Thomas Höfer](https://twitter.com/TomTriple) provides a beginner series on various datatypes from Cats.
diff --git a/docs/src/main/mdoc/datatypes.md b/docs/src/main/mdoc/datatypes.md
deleted file mode 100644
index 0d493cea49..0000000000
--- a/docs/src/main/mdoc/datatypes.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-layout: docs
-title: "Data Types"
-section: "data"
-position: 20
----
-# Data Types
-
-{% for x in site.pages %}
- {% if x.section == 'data' and x.title != page.title %}
-- [{{x.title}}]({{site.baseurl}}{{x.url}})
- {% endif %}
-{% endfor %}
diff --git a/docs/src/main/mdoc/datatypes/chain.md b/docs/src/main/mdoc/datatypes/chain.md
deleted file mode 100644
index d7a5e98f73..0000000000
--- a/docs/src/main/mdoc/datatypes/chain.md
+++ /dev/null
@@ -1,155 +0,0 @@
----
-layout: docs
-title: "Chain"
-section: "data"
-source: "core/src/main/scala/cats/data/Chain.scala"
-scaladoc: "#cats.data.Chain"
----
-
-# Chain
-
-`Chain` is a data structure that allows constant time prepending and appending.
-This makes it especially efficient when used as a `Monoid`, e.g. with `Validated` or `Writer`.
-As such it aims to be used where `List` and `Vector` incur a performance penalty.
-
-`List` is a great data type, it is very simple and easy to understand.
-It has very low overhead for the most important functions such as `fold` and `map` and also supports prepending a single element in constant time.
-
-Traversing a data structure with something like `Writer[List[Log], A]` or `ValidatedNel[Error, A]` is powerful and allows us to precisely specify what kind of iteration we want to do while remaining succint.
-However, in terms of efficiency it's a whole different story unfortunately.
-That is because both of these traversals make use of the `List` monoid (or the `NonEmptyList` semigroup), which by the nature of `List` is very inefficient.
-If you use `traverse` with a data structure with `n` elements and `Writer` or `Validated` as the `Applicative` type, you will end up with a runtime of `O(n^2)`.
-This is because, with `List`, appending a single element requires iterating over the entire data structure and therefore takes linear time.
-
-So `List` isn't all that great for this use case, so let's use `Vector` or `NonEmptyVector` instead, right?
-
-Well, `Vector` has its own problems and in this case it's unfortunately not that much faster than `List` at all. You can check [this blog post](http://www.lihaoyi.com/post/BenchmarkingScalaCollections.html#vectors-are-ok) by Li Haoyi for some deeper insight into `Vector`'s issues.
-
-
-`Chain` evolved from what used to be `fs2.Catenable` and Erik Osheim's [Chain](https://github.com/non/chain ) library.
-Similar to `List`, it is also a very simple data structure, but unlike `List` it supports both constant O(1) time `append` and `prepend`.
-This makes its `Monoid` instance super performant and a much better fit for usage with `Validated`,`Writer`, `Ior` or `Const`.
-
-To utilize this Cats includes type aliases like `ValidatedNec` or `IorNec` as well as helper functions like `groupByNec` or `Validated.invalidNec`.
-
-To get a good idea of the performance improvements, here are some benchmarks that test monoidal append (higher score is better):
-
-```
-[info] Benchmark Mode Cnt Score Error Units
-[info] CollectionMonoidBench.accumulateChain thrpt 20 51.911 ± 7.453 ops/s
-[info] CollectionMonoidBench.accumulateList thrpt 20 6.973 ± 0.781 ops/s
-[info] CollectionMonoidBench.accumulateVector thrpt 20 6.304 ± 0.129 ops/s
-```
-
-As you can see accumulating things with `Chain` is more than 7 times faster than `List` and over 8 times faster than `Vector`.
-So appending is a lot more performant than the standard library collections, but what about operations like `map` or `fold`?
-Fortunately we've also benchmarked these (again, higher score is better):
-
-```
-[info] Benchmark Mode Cnt Score Error Units
-[info] ChainBench.foldLeftLargeChain thrpt 20 117.267 ± 1.815 ops/s
-[info] ChainBench.foldLeftLargeList thrpt 20 135.954 ± 3.340 ops/s
-[info] ChainBench.foldLeftLargeVector thrpt 20 61.613 ± 1.326 ops/s
-[info]
-[info] ChainBench.mapLargeChain thrpt 20 59.379 ± 0.866 ops/s
-[info] ChainBench.mapLargeList thrpt 20 66.729 ± 7.165 ops/s
-[info] ChainBench.mapLargeVector thrpt 20 61.374 ± 2.004 ops/s
-```
-
-While not as dominant, `Chain` holds its ground fairly well.
-It won't have the random access performance of something like `Vector`, but in a lot of other cases, `Chain` seems to outperform it quite handily.
-So if you don't perform a lot of random access on your data structure, then you should be fine using `Chain` extensively instead.
-
-So next time you write any code that uses `List` or `Vector` as a `Monoid`, be sure to use `Chain` instead!
-You can also check out the benchmarks [here](https://github.com/typelevel/cats/blob/v1.3.0/bench/src/main/scala/cats/bench).
-
-## How it works
-
-`Chain` is a fairly simple data structure compared to something like `Vector`.
-It's a simple ADT that has only 4 cases.
-It is either an empty `Chain` with no elements, a singleton `Chain` with exactly one element, a concatenation of two chains or a wrapper for another collection.
-In code it looks like this:
-
-```scala mdoc
-sealed abstract class Chain[+A]
-
-case object Empty extends Chain[Nothing]
-case class Singleton[A](a: A) extends Chain[A]
-case class Append[A](left: Chain[A], right: Chain[A]) extends Chain[A]
-case class Wrap[A](seq: Seq[A]) extends Chain[A]
-```
-
-The `Append` constructor is what gives us the fast concatenation ability.
-Concatenating two existing `Chain`s, is just a call to the `Append` constructor, which is always constant time `O(1)`.
-
-In case we want to append or prepend a single element,
- all we have to do is wrap the element with the `Singleton` constructor and then use the `Append` constructor to append or prepend the `Singleton` `Chain`.
-
-The `Wrap` constructor lifts any `Seq` into a `Chain`.
-This can be useful for concatenating already created collections that don't have great concatenation performance.
-`Append(Wrap(list1), Wrap(list2)).foldMap(f)` will in general be much faster than just concatenating `list1` and `list2` and folding the result.
-
-`Chain` doesn't directly expose the `Append` and `Wrap` constructors, because the arguments might refer to an empty `Chain` or `Seq`.
-Instead of calling `Append` directly you can simply use `Chain.concat` or `++`, which will check if one of the arguments is empty:
-
-```scala
-def concat[A](c: Chain[A], c2: Chain[A]): Chain[A] =
- if (c.isEmpty) c2
- else if (c2.isEmpty) c
- else Append(c, c2)
-```
-
-To construct a `Chain` from a `Seq` you should use `Chain.fromSeq` which will also check for emptiness:
-
-```scala
-def fromSeq[A](s: Seq[A]): Chain[A] =
- if (s.isEmpty) nil
- else if (s.lengthCompare(1) == 0) one(s.head)
- else Wrap(s)
-```
-
-
-
-In conclusion `Chain` supports constant time appending and prepending, because it builds an unbalance tree of `Append`s.
-This unbalanced tree will always allow iteration in linear time.
-
-
-## NonEmptyChain
-
-`NonEmptyChain` is the non empty version of `Chain` it does not have a `Monoid` instance since it cannot be empty, but it does have a `Semigroup` instance.
-Likewise, it defines a `NonEmptyTraverse` instance, but no `TraverseFilter` instance.
-
-There are numerous ways to construct a `NonEmptyChain`, e.g. you can create one from a single element, a `NonEmptyList` or a `NonEmptyVector`:
-
-```scala mdoc
-import cats.data._
-
-NonEmptyChain(1, 2, 3, 4)
-
-NonEmptyChain.fromNonEmptyList(NonEmptyList(1, List(2, 3)))
-NonEmptyChain.fromNonEmptyVector(NonEmptyVector(1, Vector(2, 3)))
-
-NonEmptyChain.one(1)
-```
-
-
-
-You can also create an `Option` of `NonEmptyChain` from a `Chain` or any other collection type:
-
-```scala mdoc
-import cats.data._
-
-NonEmptyChain.fromChain(Chain(1, 2, 3))
-NonEmptyChain.fromSeq(List.empty[Int])
-NonEmptyChain.fromSeq(Vector(1, 2, 3))
-```
-
-Sometimes, you'll want to prepend or append a single element to a chain and return the result as a `NonEmptyChain`:
-
-```scala mdoc
-import cats.data._
-
-NonEmptyChain.fromChainAppend(Chain(1, 2, 3), 4)
-NonEmptyChain.fromChainAppend(Chain.empty[Int], 1)
-NonEmptyChain.fromChainPrepend(1, Chain(2, 3))
-```
diff --git a/docs/src/main/mdoc/datatypes/either.md b/docs/src/main/mdoc/datatypes/either.md
deleted file mode 100644
index efafca0cce..0000000000
--- a/docs/src/main/mdoc/datatypes/either.md
+++ /dev/null
@@ -1,365 +0,0 @@
----
-layout: docs
-title: "Either"
-section: "data"
-source: "core/src/main/scala/cats/syntax/either.scala"
-scaladoc: "#cats.syntax.EitherOps"
----
-# Either
-
-In day-to-day programming, it is fairly common to find ourselves writing functions that
-can fail. For instance, querying a service may result in a connection issue, or some
-unexpected JSON response.
-
-To communicate these errors it has become common practice to throw exceptions. However,
-exceptions are not tracked in any way, shape, or form by the Scala compiler. To see
-what kind of exceptions (if any) a function may throw, we have to dig through the source code.
-Then to handle these exceptions, we have to make sure we catch them at the call site.
-This all becomes even more unwieldy when we try to compose exception-throwing procedures.
-
-```scala
-val throwsSomeStuff: Int => Double = ???
-
-val throwsOtherThings: Double => String = ???
-
-val moreThrowing: String => List[Char] = ???
-
-val magic = throwsSomeStuff.andThen(throwsOtherThings).andThen(moreThrowing)
-```
-
-Assume we happily throw exceptions in our code. Looking at the types, any of those functions
-can throw any number of exceptions, we don't know. When we compose, exceptions from any of
-the constituent functions can be thrown. Moreover, they may throw the same kind of exception
-(e.g. `IllegalArgumentException`) and thus it gets tricky tracking exactly where that
-exception came from.
-
-How then do we communicate an error? By making it explicit in the data type we return.
-
-## Either
-
-### `Either` vs `Validated`
-
-In general, `Validated` is used to accumulate errors, while `Either` is used to short-circuit a computation upon the first error. For more information, see the `Validated` vs `Either` section of the [`Validated` documentation]({{ site.baseurl }}/datatypes/validated.html).
-
-### Syntax
-
-In Scala 2.10.x and 2.11.x, `Either` is unbiased. That is, usual combinators like `flatMap` and `map`
-are missing from it. Instead, you call `.right` or `.left` to get a `RightProjection` or
-`LeftProjection` (respectively) which does have the combinators. The direction of the projection indicates the direction
-of bias. For instance, calling `map` on a `RightProjection` acts on the `Right` of an `Either`.
-
-```scala mdoc
-val e1: Either[String, Int] = Right(5)
-e1.right.map(_ + 1)
-
-val e2: Either[String, Int] = Left("hello")
-e2.right.map(_ + 1)
-```
-
-Note the return types are themselves back to `Either`, so if we want to make more calls to
-`flatMap` or `map` then we again must call `right` or `left`.
-
-However, the convention is almost always to right-bias `Either`. Indeed in Scala 2.12.x `Either` is
-[right-biased](https://github.com/scala/scala/pull/5135) by default.
-
-More often than not we want to just bias towards one side and call it a day - by convention,
-the right side is most often chosen. In Scala 2.12.x this convention
-[is implemented](https://github.com/scala/scala/pull/5135)
-in the standard library. Since Cats builds on 2.10.x and 2.11.x, the gaps have been filled via syntax
-enrichments available under `cats.syntax.either._` or `cats.implicits._`.
-
-```scala mdoc
-import cats.implicits._
-
-val right: Either[String, Int] = Right(5)
-right.map(_ + 1)
-
-val left: Either[String, Int] = Left("hello")
-left.map(_ + 1)
-```
-
-For the rest of this tutorial we will assume the syntax enrichment is in scope giving us right-biased `Either`
-and a bunch of other useful combinators (both on `Either` and the companion object).
-
-Because `Either` is right-biased, it is possible to define a `Monad` instance for it.
-Since we only ever want the computation to continue in the case of `Right`, we fix the left type parameter
-and leave the right one free.
-
-*Note*: the example below assumes usage of the [kind-projector compiler plugin](https://github.com/typelevel/kind-projector) and will not compile if it is not being used in a project.
-
-```scala mdoc:silent
-import cats.Monad
-
-implicit def eitherMonad[Err]: Monad[Either[Err, *]] =
- new Monad[Either[Err, *]] {
- def flatMap[A, B](fa: Either[Err, A])(f: A => Either[Err, B]): Either[Err, B] =
- fa.flatMap(f)
-
- def pure[A](x: A): Either[Err, A] = Either.right(x)
-
- @annotation.tailrec
- def tailRecM[A, B](a: A)(f: A => Either[Err, Either[A, B]]): Either[Err, B] =
- f(a) match {
- case Right(Right(b)) => Either.right(b)
- case Right(Left(a)) => tailRecM(a)(f)
- case l@Left(_) => l.rightCast[B] // Cast the right type parameter to avoid allocation
- }
- }
-```
-
-### Example usage: Round 1
-As a running example, we will have a series of functions that will parse a string into an integer,
-take the reciprocal, and then turn the reciprocal into a string.
-
-In exception-throwing code, we would have something like this:
-
-```scala mdoc:silent
-object ExceptionStyle {
- def parse(s: String): Int =
- if (s.matches("-?[0-9]+")) s.toInt
- else throw new NumberFormatException(s"${s} is not a valid integer.")
-
- def reciprocal(i: Int): Double =
- if (i == 0) throw new IllegalArgumentException("Cannot take reciprocal of 0.")
- else 1.0 / i
-
- def stringify(d: Double): String = d.toString
-}
-```
-
-Instead, let's make the fact that some of our functions can fail explicit in the return type.
-
-```scala mdoc:silent
-object EitherStyle {
- def parse(s: String): Either[Exception, Int] =
- if (s.matches("-?[0-9]+")) Either.right(s.toInt)
- else Either.left(new NumberFormatException(s"${s} is not a valid integer."))
-
- def reciprocal(i: Int): Either[Exception, Double] =
- if (i == 0) Either.left(new IllegalArgumentException("Cannot take reciprocal of 0."))
- else Either.right(1.0 / i)
-
- def stringify(d: Double): String = d.toString
-}
-```
-
-Now, using combinators like `flatMap` and `map`, we can compose our functions together.
-
-```scala mdoc:silent
-import EitherStyle._
-
-def magic(s: String): Either[Exception, String] =
- parse(s).flatMap(reciprocal).map(stringify)
-```
-
-With the composite function that we actually care about, we can pass in strings and then pattern
-match on the exception. Because `Either` is a sealed type (often referred to as an algebraic data type,
-or ADT), the compiler will complain if we do not check both the `Left` and `Right` case.
-
-```scala mdoc
-magic("123") match {
- case Left(_: NumberFormatException) => println("not a number!")
- case Left(_: IllegalArgumentException) => println("can't take reciprocal of 0!")
- case Left(_) => println("got unknown exception")
- case Right(s) => println(s"Got reciprocal: ${s}")
-}
-```
-
-Not bad - if we leave out any of those clauses the compiler will yell at us, as it should. However,
-note the `Left(_)` clause - the compiler will complain if we leave that out because it knows
-that given the type `Either[Exception, String]`, there can be inhabitants of `Left` that are not
-`NumberFormatException` or `IllegalArgumentException`. However, we "know" by inspection of the source
-that those will be the only exceptions thrown, so it seems strange to have to account for other exceptions.
-This implies that there is still room to improve.
-
-### Example usage: Round 2
-Instead of using exceptions as our error value, let's instead enumerate explicitly the things that
-can go wrong in our program.
-
-```scala mdoc:reset:silent
-import cats.implicits._
-
-object EitherStyle {
- sealed abstract class Error
- final case class NotANumber(string: String) extends Error
- case object NoZeroReciprocal extends Error
-
- def parse(s: String): Either[Error, Int] =
- if (s.matches("-?[0-9]+")) Either.right(s.toInt)
- else Either.left(NotANumber(s))
-
- def reciprocal(i: Int): Either[Error, Double] =
- if (i == 0) Either.left(NoZeroReciprocal)
- else Either.right(1.0 / i)
-
- def stringify(d: Double): String = d.toString
-
- def magic(s: String): Either[Error, String] =
- parse(s).flatMap(reciprocal).map(stringify)
-}
-```
-
-For our little module, we enumerate any and all errors that can occur. Then, instead of using
-exception classes as error values, we use one of the enumerated cases. Now when we pattern
-match, we get much nicer matching. Moreover, since `Error` is `sealed`, no outside code can
-add additional subtypes which we might fail to handle.
-
-```scala mdoc
-import EitherStyle._
-
-magic("123") match {
- case Left(NotANumber(_)) => println("not a number!")
- case Left(NoZeroReciprocal) => println("can't take reciprocal of 0!")
- case Right(s) => println(s"Got reciprocal: ${s}")
-}
-```
-
-## Either in the small, Either in the large
-Once you start using `Either` for all your error-handling, you may quickly run into an issue where
-you need to call into two separate modules which give back separate kinds of errors.
-
-```scala mdoc:silent
-sealed abstract class DatabaseError
-trait DatabaseValue
-
-object Database {
- def databaseThings(): Either[DatabaseError, DatabaseValue] = ???
-}
-
-sealed abstract class ServiceError
-trait ServiceValue
-
-object Service {
- def serviceThings(v: DatabaseValue): Either[ServiceError, ServiceValue] = ???
-}
-```
-
-Let's say we have an application that wants to do database things, and then take database
-values and do service things. Glancing at the types, it looks like `flatMap` will do it.
-
-```scala
-def doApp = Database.databaseThings().flatMap(Service.serviceThings)
-```
-
-This line will compile and work as expected, no matter if you're on 2.12 or an earlier
-version of Scala. The `flatMap` we get here (either provided by Cats's `Either` syntax for
-Scala 2.10 and 2.11, or, in Scala 2.12, a method on `Either`) has this signature:
-
-```scala
-def flatMap[AA >: A, Y](f: (B) => Either[AA, Y]): Either[AA, Y]
-```
-
-This `flatMap` is different from the ones you'll find on `List` or `Option`, for example, in that it
-has two type parameters, with the extra `AA` parameter allowing us to `flatMap` into an `Either`
-with a different type on the left side.
-
-This behavior is consistent with the covariance of `Either`, and in some cases it can be convenient,
-but it also makes it easy to run into nasty variance issues - such as `Object` being inferred as the
-type of the left side, as it is in this case.
-
-
-### Solution 1: Application-wide errors
-We may then be tempted to make our entire application share an error data type.
-
-```scala mdoc:nest:silent
-sealed abstract class AppError
-case object DatabaseError1 extends AppError
-case object DatabaseError2 extends AppError
-case object ServiceError1 extends AppError
-case object ServiceError2 extends AppError
-
-trait DatabaseValue
-
-object Database {
- def databaseThings(): Either[AppError, DatabaseValue] = ???
-}
-
-object Service {
- def serviceThings(v: DatabaseValue): Either[AppError, ServiceValue] = ???
-}
-
-def doApp = Database.databaseThings().flatMap(Service.serviceThings)
-```
-
-This certainly works, or at least it compiles. But consider the case where another module wants to just use
-`Database`, and gets an `Either[AppError, DatabaseValue]` back. Should it want to inspect the errors, it
-must inspect **all** the `AppError` cases, even though it was only intended for `Database` to use
-`DatabaseError1` or `DatabaseError2`.
-
-### Solution 2: ADTs all the way down
-Instead of lumping all our errors into one big ADT, we can instead keep them local to each module, and have
-an application-wide error ADT that wraps each error ADT we need.
-
-```scala mdoc:nest:silent
-sealed abstract class DatabaseError
-trait DatabaseValue
-
-object Database {
- def databaseThings(): Either[DatabaseError, DatabaseValue] = ???
-}
-
-sealed abstract class ServiceError
-trait ServiceValue
-
-object Service {
- def serviceThings(v: DatabaseValue): Either[ServiceError, ServiceValue] = ???
-}
-
-sealed abstract class AppError
-object AppError {
- final case class Database(error: DatabaseError) extends AppError
- final case class Service(error: ServiceError) extends AppError
-}
-```
-
-Now in our outer application, we can wrap/lift each module-specific error into `AppError` and then
-call our combinators as usual. `Either` provides a convenient method to assist with this, called `Either.leftMap` -
-it can be thought of as the same as `map`, but for the `Left` side.
-
-```scala mdoc:silent
-def doApp: Either[AppError, ServiceValue] =
- Database.databaseThings().leftMap[AppError](AppError.Database).
- flatMap(dv => Service.serviceThings(dv).leftMap(AppError.Service))
-```
-
-Hurrah! Each module only cares about its own errors as it should be, and more composite modules have their
-own error ADT that encapsulates each constituent module's error ADT. Doing this also allows us to take action
-on entire classes of errors instead of having to pattern match on each individual one.
-
-```scala mdoc:silent
-def awesome =
- doApp match {
- case Left(AppError.Database(_)) => "something in the database went wrong"
- case Left(AppError.Service(_)) => "something in the service went wrong"
- case Right(_) => "everything is alright!"
- }
-```
-
-
-## Working with exception-y code
-There will inevitably come a time when your nice `Either` code will have to interact with exception-throwing
-code. Handling such situations is easy enough.
-
-```scala mdoc
-val either: Either[NumberFormatException, Int] =
- try {
- Either.right("abc".toInt)
- } catch {
- case nfe: NumberFormatException => Either.left(nfe)
- }
-```
-
-However, this can get tedious quickly. `Either` has a `catchOnly` method on its companion object
-(via syntax enrichment) that allows you to pass it a function, along with the type of exception you want to catch, and does the
-above for you.
-
-```scala mdoc:nest
-val either: Either[NumberFormatException, Int] =
- Either.catchOnly[NumberFormatException]("abc".toInt)
-```
-
-If you want to catch all (non-fatal) throwables, you can use `catchNonFatal`.
-
-```scala mdoc:nest
-val either: Either[Throwable, Int] = Either.catchNonFatal("abc".toInt)
-```
diff --git a/docs/src/main/mdoc/typeclasses.md b/docs/src/main/mdoc/typeclasses.md
deleted file mode 100644
index 8a5ab9b81e..0000000000
--- a/docs/src/main/mdoc/typeclasses.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-layout: docs
-title: "Type Classes"
-section: "typeclasses"
-position: 10
----
-{% include_relative typeclasses/typeclasses.md %}
diff --git a/docs/src/main/resources/microsite/css/override.css b/docs/src/main/resources/microsite/css/override.css
deleted file mode 100644
index 5a539f14f7..0000000000
--- a/docs/src/main/resources/microsite/css/override.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.technologies {
- display: none;
-}
\ No newline at end of file
diff --git a/docs/src/main/resources/microsite/data/menu.yml b/docs/src/main/resources/microsite/data/menu.yml
deleted file mode 100644
index b967b9553d..0000000000
--- a/docs/src/main/resources/microsite/data/menu.yml
+++ /dev/null
@@ -1,220 +0,0 @@
-options:
-
- #############################
- # Type Classes Menu Options #
- #############################
-
- - title: Type Classes
- url: typeclasses.html
- menu_type: typeclasses
- menu_section: typeclasses
-
- - title: Semigroups and Monoids
- url: typeclasses/semigroup.html
- menu_type: typeclasses
- menu_section: semigroupsandmonoids
-
- nested_options:
- - title: Semigroup
- url: typeclasses/semigroup.html
- menu_section: semigroupsandmonoids
- - title: Monoid
- url: typeclasses/monoid.html
- menu_section: semigroupsandmonoids
-
- - title: Applicative and Traversable Functors
- url: typeclasses/applicativetraverse.html
- menu_type: typeclasses
- menu_section: applicative
-
- nested_options:
- - title: Functor
- url: typeclasses/functor.html
- menu_section: applicative
- - title: Applicative
- url: typeclasses/applicative.html
- menu_section: applicative
- - title: Traverse
- url: typeclasses/traverse.html
- menu_type: typeclasses
- menu_section: applicative
-
- - title: Monads
- url: typeclasses/monad.html
- menu_type: typeclasses
- menu_section: monads
-
- - title: Comonads
- url: typeclasses/comonad.html
- menu_type: typeclasses
- menu_section: comonads
-
- - title: Variance and Functors
- url: typeclasses/functor.html
- menu_type: typeclasses
- menu_section: variance
-
- nested_options:
- - title: Functor
- url: typeclasses/functor.html
- menu_section: variance
- - title: Contravariant
- url: typeclasses/contravariant.html
- menu_section: variance
- - title: ContravariantMonoidal
- url: typeclasses/contravariantmonoidal.html
- menu_type: typeclasses
- - title: Invariant
- url: typeclasses/invariant.html
- menu_section: variance
- - title: InvariantMonoidal
- url: typeclasses/invariantmonoidal.html
- menu_section: variance
-
- - title: Alternative
- url: typeclasses/alternative.html
- menu_type: typeclasses
-
- - title: Bifunctor
- url: typeclasses/bifunctor.html
- menu_type: typeclasses
-
- - title: Eq
- url: typeclasses/eq.html
- menu_type: typeclasses
-
- - title: Foldable
- url: typeclasses/foldable.html
- menu_type: typeclasses
-
- - title: Parallel
- url: typeclasses/parallel.html
- menu_type: typeclasses
-
- - title: SemigroupK
- url: typeclasses/semigroupk.html
- menu_type: typeclasses
-
- - title: MonoidK
- url: typeclasses/monoidk.html
- menu_type: typeclasses
-
- - title: Show
- url: typeclasses/show.html
- menu_type: typeclasses
-
- - title: Reducible
- url: typeclasses/reducible.html
- menu_type: typeclasses
-
- - title: ApplicativeError and MonadError
- url: typeclasses/applicativemonaderror.html
- menu_type: typeclasses
-
- - title: NonEmptyTraverse
- url: typeclasses/nonemptytraverse.html
- menu_type: typeclasses
-
- - title: Arrow
- url: typeclasses/arrow.html
- menu_type: typeclasses
-
- - title: Arrow Choice
- url: typeclasses/arrowchoice.html
- menu_type: typeclasses
-
- - title: Law Testing
- url: typeclasses/lawtesting.html
- menu_type: typeclasses
-
- ###########################
- # Data Types Menu Options #
- ###########################
-
- - title: Data Types
- url: datatypes.html
- menu_type: data
-
- - title: Chain
- url: datatypes/chain.html
- menu_type: data
-
- - title: Const
- url: datatypes/const.html
- menu_type: data
-
- - title: ContT
- url: datatypes/contt.html
- menu_type: data
-
- - title: Either
- url: datatypes/either.html
- menu_type: data
-
- - title: Eval
- url: datatypes/eval.html
- menu_type: data
-
- - title: FreeApplicatives
- url: datatypes/freeapplicative.html
- menu_type: data
-
- - title: FreeMonads
- url: datatypes/freemonad.html
- menu_type: data
-
- - title: FunctionK
- url: datatypes/functionk.html
- menu_type: data
-
- - title: Id
- url: datatypes/id.html
- menu_type: data
-
- - title: Ior
- url: datatypes/ior.html
- menu_type: data
-
- - title: Kleisli
- url: datatypes/kleisli.html
- menu_type: data
-
- - title: Writer
- url: datatypes/writer.html
- menu_type: data
-
- - title: WriterT
- url: datatypes/writert.html
- menu_type: data
-
- - title: Nested
- url: datatypes/nested.html
- menu_type: data
-
- - title: NonEmptyList
- url: datatypes/nel.html
- menu_type: data
-
- - title: OneAnd
- url: datatypes/oneand.html
- menu_type: data
-
- - title: OptionT
- url: datatypes/optiont.html
- menu_type: data
-
- - title: EitherT
- url: datatypes/eithert.html
- menu_type: data
-
- - title: IorT
- url: datatypes/iort.html
- menu_type: data
-
- - title: State
- url: datatypes/state.html
- menu_type: data
-
- - title: Validated
- url: datatypes/validated.html
- menu_type: data
diff --git a/docs/src/main/mdoc/typeclasses/typeclasses.md b/docs/typeclasses.md
similarity index 80%
rename from docs/src/main/mdoc/typeclasses/typeclasses.md
rename to docs/typeclasses.md
index cef20f7734..85a4d32f69 100644
--- a/docs/src/main/mdoc/typeclasses/typeclasses.md
+++ b/docs/typeclasses.md
@@ -1,4 +1,4 @@
-# Type classes
+# Type Classes
Type classes are a powerful tool used in functional programming to enable ad-hoc polymorphism, more commonly
known as overloading. Where many object-oriented languages leverage subtyping for polymorphic code, functional
programming tends towards a combination of parametric polymorphism (think type parameters, like Java generics)
@@ -112,7 +112,7 @@ We can do this through Scala's implicit mechanism.
```scala mdoc:reset-object
import cats.Monoid
-object Demo {
+object Demo {
final case class Pair[A, B](first: A, second: B)
object Pair {
@@ -187,8 +187,6 @@ def combineAll[A : Monoid](list: List[A]): A =
list.foldRight(Monoid[A].empty)(Monoid[A].combine)
```
-Cats uses [simulacrum][simulacrum] for defining type classes which will auto-generate such an `apply` method.
-
# Laws
Conceptually, all type classes come with laws. These laws constrain implementations for a given
@@ -225,7 +223,7 @@ val result = Monoid[Int].combine(sumLeft, sumRight)
Cats provides laws for type classes via the `kernel-laws` and `laws` modules which makes law checking
type class instances easy.
-You can find out more about law testing [here](typeclasses/lawtesting.html).
+You can find out more about law testing [here](typeclasses/lawtesting.md).
## Type classes in Cats
@@ -235,23 +233,23 @@ From [cats-infographic by @tpolecat](https://github.com/tpolecat/cats-infographi
## Incomplete type class instances in cats
-Originally from [@alexknvl](https://gist.github.com/alexknvl/d63508ddb6a728015ace53cb70a1fd5d)
+Originally from [@hobwekiva](https://gist.github.com/hobwekiva/d63508ddb6a728015ace53cb70a1fd5d)
-| Type | Functor | Apply | Applicative | Monad | MonoidK | ApplicativeError | MonadError | CoflatMap | Comonad |
-| --------------- |:-------:|:-----------------:|:-----------:|:-----:|:-------:|:-----------------:|:----------:|:---------:|:-------:|
-| Id[A] | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✗ | ✔ | ✔ |
-| Eval[A] | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✗ | ✔ | ✔ |
-| Option[A] | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ |
-| Const[K, A] | ✔ | ✔ (`K:Monoid`) | ✔ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
-| Either[E, A] | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ |
-| List[A] | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ |
-| NonEmptyList[A] | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✗ | ✔ | ✔ |
-| Stream[A] | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ |
-| Map[K, A] | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ | ✗ |
-| Validated[E, A] | ✔ | ✔ (`E: Semigroup`)| ✔ | ✗ | ✗ | ✔ (`E: Semigroup`)| ✗ | ✗ | ✗ |
-| Reader[E, A] | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✗ | ✗ | ✗ |
-| Writer[E, A] | ✔ | ✔ (`E:Monoid`) | ✔ | ✔ | ✗ | ✗ | ✗ | ✔ | ✗ |
+| Type | Functor | Apply | Applicative | Monad | MonoidK | ApplicativeError | MonadError | CoflatMap | Comonad | Bimonad |
+| --------------- |:-------:|:-----------------:|:-----------:|:-----:|:-------:|:-----------------:|:----------:|:---------:|:-------:|:-------:|
+| `Id[A]` | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✗ | ✔ | ✔ |✔ |
+| `Eval[A]` | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✗ | ✔ | ✔ |✔ |
+| `Option[A]` | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ |✗ |
+| `Const[K, A]` | ✔ | ✔ (`K:Monoid`) | ✔ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |✗ |
+| `Either[E, A]` | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ |✗ |
+| `List[A]` | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ |✗ |
+| `NonEmptyList[A]` | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✗ | ✔ | ✔ |✔ |
+| `Stream[A]` | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ |✗ |
+| `Map[K, A]` | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ | ✗ |✗ |
+| `Validated[E, A]` | ✔ | ✔ (`E: Semigroup`)| ✔ | ✗ | ✗ | ✔ (`E: Semigroup`)| ✗ | ✗ | ✗ |✗ |
+| `Reader[E, A]` | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | ✗ | ✗ | ✗ |✗ |
+| `Writer[E, A]` | ✔ | ✔ (`E:Monoid`) | ✔ | ✔ | ✗ | ✗ | ✗ | ✔ | ✗ |✗ |
@@ -262,4 +260,3 @@ Originally from [@alexknvl](https://gist.github.com/alexknvl/d63508ddb6a728015ac
[fbounds]: http://tpolecat.github.io/2015/04/29/f-bounds.html "Returning the "Current" Type in Scala"
-[simulacrum]: https://github.com/typelevel/simulacrum "First class syntax support for type classes in Scala"
diff --git a/docs/src/main/mdoc/typeclasses/alternative.md b/docs/typeclasses/alternative.md
similarity index 91%
rename from docs/src/main/mdoc/typeclasses/alternative.md
rename to docs/typeclasses/alternative.md
index 3f03ada921..10291d5922 100644
--- a/docs/src/main/mdoc/typeclasses/alternative.md
+++ b/docs/typeclasses/alternative.md
@@ -1,12 +1,8 @@
----
-layout: docs
-title: "Alternative"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Alternative.scala"
-scaladoc: "#cats.Alternative"
----
# Alternative
-Alternative extends [`Applicative`](applicative.html) with a [`MonoidK`](monoidk.html).
+
+API Documentation: @:api(cats.Alternative)
+
+Alternative extends [`Applicative`](applicative.md) with a [`MonoidK`](monoidk.md).
Let's stub out all the operations just to remind ourselves what that gets us.
```scala mdoc:silent
@@ -28,11 +24,13 @@ As you might recall, `pure` wraps values in the context; `ap` allows us to do ca
Like other type classes, `Alternative` instances must obey some laws, in addition to those otherwise applying to `MonoidK` and `Applicative instances`:
* Right Absorption: Applying a contextual function `F[A => B]` to `empty [A]` should be `empty [B]`.
- * `ff ap F.empty[A] = F.empty[B]`.
+ * `ff ap F.empty[A] = F.empty[B]`.
+
* Left Distributivity: Mapping over a combined element must be the combinations of the mapped elements.
- * `(fa <+> fb) map f = ((fa map f) <+> (fb map f))` where `fa: F[A]` and `fb: F[B]` and `f: A => B`.
+ * `(fa <+> fb) map f = ((fa map f) <+> (fb map f))` where `fa: F[A]` and `fb: F[B]` and `f: A => B`.
+
* Right Distributivity: Applying the combination of two functions must be the combination of their applications.
- * `(ff <+> fg) ap fa = (ff ap fa) <+> (fg ap fa)` where `ff: F[A => B]`, `fg: F[A => B]`, and `fa: F[A]`.
+ * `(ff <+> fg) ap fa = (ff ap fa) <+> (fg ap fa)` where `ff: F[A => B]`, `fg: F[A => B]`, and `fa: F[A]`.
These laws guarantee the compatibility of the otherwise possibly independent `Applicative` and `MonoidK` structures.
@@ -44,7 +42,7 @@ The relevant imports:
```scala mdoc:reset:silent
import cats.Alternative
-import cats.implicits._
+import cats.syntax.all._
```
And what we can do with them:
@@ -79,7 +77,7 @@ object Decoder {
Then, we can implement an `Alternative` instance for this type like so:
```scala mdoc:silent
-implicit val decoderAlternative = new Alternative[Decoder] {
+implicit val decoderAlternative: Alternative[Decoder] = new Alternative[Decoder] {
def pure[A](a: A) = Decoder.from(Function.const(Right(a)))
def empty[A] = Decoder.from(Function.const(Left(new Error("No dice."))))
diff --git a/docs/src/main/mdoc/typeclasses/applicative.md b/docs/typeclasses/applicative.md
similarity index 88%
rename from docs/src/main/mdoc/typeclasses/applicative.md
rename to docs/typeclasses/applicative.md
index 63801c6279..bf654c7533 100644
--- a/docs/src/main/mdoc/typeclasses/applicative.md
+++ b/docs/typeclasses/applicative.md
@@ -1,12 +1,8 @@
----
-layout: docs
-title: "Applicative"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Applicative.scala"
-scaladoc: "#cats.Applicative"
----
# Applicative
-`Applicative` extends [`Functor`](functor.html) with an `ap` and `pure` method.
+
+API Documentation: @:api(cats.Applicative)
+
+`Applicative` extends [`Functor`](functor.md) with an `ap` and `pure` method.
```scala mdoc:silent
import cats.Functor
@@ -87,7 +83,7 @@ def product3[F[_]: Applicative, A, B, C](fa: F[A], fb: F[B], fc: F[C]): F[(A, B,
Let's see what happens if we try to compose two effectful values with just `map`.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
val f: (Int, Char) => Double = (i, c) => (i + c).toDouble
@@ -104,12 +100,12 @@ but `map` doesn't give us enough power to do that. Hence, `ap`.
## Applicatives compose
-Like [`Functor`](functor.html), `Applicative`s compose. If `F` and `G` have `Applicative` instances, then so
+Like [`Functor`](functor.md), `Applicative`s compose. If `F` and `G` have `Applicative` instances, then so
does `F[G[_]]`.
```scala mdoc:silent
import cats.data.Nested
-import cats.implicits._
+import cats.syntax.all._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
@@ -179,7 +175,7 @@ This works...but if we look carefully at the implementation there's nothing `Opt
another example let's implement the same function but for `Either`.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
def traverseEither[E, A, B](as: List[A])(f: A => Either[E, B]): Either[E, List[B]] =
as.foldRight(Right(List.empty[B]): Either[E, List[B]]) { (a: A, acc: Either[E, List[B]]) =>
@@ -210,7 +206,7 @@ This function is provided by Cats via the `Traverse[List]` instance and syntax,
tutorial.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
```
```scala mdoc
@@ -261,7 +257,7 @@ Applicative[Option].map3(username, password, url)(attemptConnect)
With the applicative syntax, we can change this to the slightly shorter:
```scala mdoc
-import cats.implicits._
+import cats.syntax.all._
(username, password, url).mapN(attemptConnect)
```
@@ -269,6 +265,20 @@ import cats.implicits._
We don't have to mention the type or specify the number of values we're composing
together, so there's a little less boilerplate here.
+Another very useful `Apply` syntax is `tupled`, which allows a tuple of effectful values to be composed into a single effectful value containing a tuple.
+
+```scala mdoc
+import cats.syntax.all._
+
+val optPair: Option[(String, String)] = (username, password).tupled
+```
+
+### See also Parallel variants
+
+Both `tupled` and `mapN` have [parallel](parallel.md) variant operations, named `parTupled` and `parMapN` respectively. Regular `tupled`/`mapN` evaluate their effects from left to right ("sequentially"), while `parTupled`/`parMapN` evaluate in an indeterminate order, or in parallel.
+
+The difference can be understood intuitively when the effect is an executable task, such as `IO` from [Cats Effect](https://typelevel.org/cats-effect/docs/concepts#concurrent). In this case, the parallel variants enable you to compose tuples of tasks into a single task that will run its sub-tasks concurrently.
+
## Further Reading
* [Applicative Programming with Effects][applicativePaper] - McBride, Patterson. JFP 2008.
diff --git a/docs/src/main/mdoc/typeclasses/applicativemonaderror.md b/docs/typeclasses/applicativemonaderror.md
similarity index 81%
rename from docs/src/main/mdoc/typeclasses/applicativemonaderror.md
rename to docs/typeclasses/applicativemonaderror.md
index df96ca508a..be246a1cd3 100644
--- a/docs/src/main/mdoc/typeclasses/applicativemonaderror.md
+++ b/docs/typeclasses/applicativemonaderror.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Applicative Error"
-section: "typeclasses"
-source: "core/src/main/scala/cats/ApplicativeError.scala"
-scaladoc: "#cats.ApplicativeError"
----
# ApplicativeError and MonadError
+API Documentation: @:api(cats.ApplicativeError), @:api(cats.MonadError)
+
## Applicative Error
### Description
@@ -16,7 +11,7 @@ that represent the quality of an exception or an error, for example, `Either[E,
### TypeClass Definition
`ApplicativeError` is defined by the following `trait`
-```
+```scala
trait ApplicativeError[F[_], E] extends Applicative[F] {
def raiseError[A](e: E): F[A]
def handleErrorWith[A](fa: F[A])(f: E => F[A]): F[A]
@@ -47,7 +42,7 @@ create multiple functions with different "container" types.
```scala mdoc:silent
import cats._
-import cats.implicits._
+import cats.syntax.all._
def attemptDivideApplicativeError[F[_]](x: Int, y: Int)(implicit ae: ApplicativeError[F, String]): F[Int] = {
if (y == 0) ae.raiseError("divisor is error")
@@ -93,7 +88,7 @@ when calling `attemptDivideApplicativeError`. Notice that
so we make no other changes.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
import cats.data.Validated
type MyValidated[A] = Validated[String, A]
@@ -115,14 +110,14 @@ val j = attemptDivideApplicativeError[Validated[String, *]](30, 10)
### It is an `Applicative` after all
-As a Reminder, this is an [`Applicative`](/cats/typeclasses/applicative.html)
+As a Reminder, this is an [`Applicative`](applicative.md)
so all the methods of `Applicative` are available to you to use in
manipulating your values, `ap`, `mapN`, etc. In the following example, notice
we are using `Applicative`'s `map2`, and of course, `pure` which also is a
form of `Applicative`.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
def attemptDivideApplicativeErrorWithMap2[F[_]](x: Int, y: Int)(implicit ae: ApplicativeError[F, String]): F[_] = {
if (y == 0) ae.raiseError("divisor is error")
else {
@@ -144,7 +139,7 @@ into the `handler` method, where this method will pattern match on the message
and provide an alternative outcome.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
def attemptDivideApplicativeErrorAbove2[F[_]](x: Int, y: Int)(implicit ae: ApplicativeError[F, String]): F[Int] =
if (y == 0) ae.raiseError("Bad Math")
else if (y == 1) ae.raiseError("Waste of Time")
@@ -181,6 +176,42 @@ Running the following will result in `Right(0)`
handlerErrorWith(attemptDivideApplicativeErrorAbove2(3, 0))
```
+### Handling Exceptions
+There will inevitably come a time when your nice `ApplicativeError` code will
+have to interact with exception-throwing code. Handling such situations is easy
+enough.
+
+```scala mdoc
+def parseInt[F[_]](input: String)(implicit F: ApplicativeError[F, Throwable]): F[Int] =
+ try {
+ F.pure(input.toInt)
+ } catch {
+ case nfe: NumberFormatException => F.raiseError(nfe)
+ }
+
+parseInt[Either[Throwable, *]]("123")
+parseInt[Either[Throwable, *]]("abc")
+```
+
+However, this can get tedious quickly. `ApplicativeError` has a `catchOnly`
+method that allows you to pass it a function, along with the type of exception
+you want to catch, and does the above for you.
+
+```scala mdoc:nest
+def parseInt[F[_]](input: String)(implicit F: ApplicativeError[F, Throwable]): F[Int] =
+ F.catchOnly[NumberFormatException](input.toInt)
+
+parseInt[Either[Throwable, *]]("abc")
+```
+
+If you want to catch all (non-fatal) throwables, you can use `catchNonFatal`.
+
+```scala mdoc:nest
+def parseInt[F[_]](input: String)(implicit F: ApplicativeError[F, Throwable]): F[Int] = F.catchNonFatal(input.toInt)
+
+parseInt[Either[Throwable, *]]("abc")
+```
+
## MonadError
### Description
@@ -195,7 +226,7 @@ The Definition for `MonadError` extends `Monad` which provides the
methods, `flatMap`, `whileM_`. `MonadError` also provides error
handling methods like `ensure`, `ensureOr`, `adaptError`, `rethrow`.
-```
+```scala
trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F] {
def ensure[A](fa: F[A])(error: => E)(predicate: A => Boolean): F[A]
def ensureOr[A](fa: F[A])(error: A => E)(predicate: A => Boolean): F[A]
@@ -230,16 +261,16 @@ With the methods that we will compose in place let's create a method that will
compose the above methods using a for comprehension which
interprets to a `flatMap`-`map` combination.
-`getTemperatureFromByCoordinates` parameterized type
-`[F[_]:MonadError[*[_], String]` injects `F[_]` into `MonadError[*[_], String]`
+`getTemperatureByCoordinates`'s parameterized type
+`[F[_]:MonadError[*[_], String]` injects `F[_]` into `MonadError[*[_], String]`;
thus if the "error type" you wish to use is `Either[String, *]`, the `Either`
would be placed in the hole of `MonadError`, in this case,
`MonadError[Either[String, *], String]`
-`getTemperatureFromByCoordinates` accepts a `Tuple2` of `Int` and `Int`, and we
-return `F` which represents our `MonadError` which can be a type like `Either` or
-`Validated`. In the method, since either `getCityClosestToCoordinate` and
-`getTemperatureByCity` both return potential error types and they are monadic we can
+`getTemperatureByCoordinates` accepts a `Tuple2` of `Int` and `Int` and
+returns `F`, which represents our `MonadError`, which can be a type like `Either` or
+`Validated`. In the method, since `getCityClosestToCoordinate` and
+`getTemperatureByCity` both return potential error types and they are monadic, we can
compose them with a for comprehension.
```scala mdoc:silent
@@ -249,17 +280,14 @@ def getTemperatureByCoordinates[F[_]: MonadError[*[_], String]](x: (Int, Int)):
}
```
-Invoking `getTemperatureByCoordinates` we can call it with the following sample,
-which will return `78`.
-
-NOTE: infix `->` creates a `Tuple2`. `1 -> "Bob"` is the same as `(1, "Bob")`
+We can call `getTemperatureByCoordinates` with the following sample, which will return `78`.
```scala mdoc:silent
type MyEither[A] = Either[String, A]
-getTemperatureByCoordinates[MyEither](44 -> 93)
+getTemperatureByCoordinates[MyEither]((44, 93))
```
-With TypeLevel Cats, how you structure your methods is up to you, if you wanted to
+With TypeLevel Cats, how you structure your methods is up to you: if you wanted to
create `getTemperatureByCoordinates` without a Scala
[context bound](https://docs.scala-lang.org/tutorials/FAQ/context-bounds.html) for `MonadError`,
but create an `implicit` parameter for your `MonadError` you can have access to some
@@ -271,7 +299,7 @@ specialized methods, like `raiseError`, to raise an error representation
when things go wrong.
```scala mdoc:silent
-def getTemperatureFromByCoordinatesAlternate[F[_]](x: (Int, Int))(implicit me: MonadError[F, String]): F[Int] = {
+def getTemperatureByCoordinatesAlternate[F[_]](x: (Int, Int))(implicit me: MonadError[F, String]): F[Int] = {
if (x._1 < 0 || x._2 < 0) me.raiseError("Invalid Coordinates")
else for { c <- getCityClosestToCoordinate[F](x)
t <- getTemperatureByCity[F](c) } yield t
diff --git a/docs/src/main/mdoc/typeclasses/applicativetraverse.md b/docs/typeclasses/applicativetraverse.md
similarity index 94%
rename from docs/src/main/mdoc/typeclasses/applicativetraverse.md
rename to docs/typeclasses/applicativetraverse.md
index ccdda75e3b..5786d7d2d3 100644
--- a/docs/src/main/mdoc/typeclasses/applicativetraverse.md
+++ b/docs/typeclasses/applicativetraverse.md
@@ -1,10 +1,3 @@
----
-layout: docs
-title: "Applicative and Traversable Functors"
-section: "typeclasses"
-scaladoc: "#cats.Functor"
----
-
# Applicative and Traversable Functors
## An example from the standard library
diff --git a/docs/src/main/mdoc/typeclasses/arrow.md b/docs/typeclasses/arrow.md
similarity index 98%
rename from docs/src/main/mdoc/typeclasses/arrow.md
rename to docs/typeclasses/arrow.md
index 5f1b02be86..144f496406 100644
--- a/docs/src/main/mdoc/typeclasses/arrow.md
+++ b/docs/typeclasses/arrow.md
@@ -1,15 +1,11 @@
----
-layout: docs
-title: "Arrow"
-section: "typeclasses"
-source: "core/src/main/scala/cats/arrow/Arrow.scala"
-scaladoc: "#cats.arrow.Arrow"
----
# Arrow
+API Documentation: @:api(cats.arrow.Arrow)
+
`Arrow` is a type class for modeling composable relationships between two types. One example of such a composable relationship is function `A => B`; other examples include `cats.data.Kleisli`(wrapping an `A => F[B]`, also known as `ReaderT`), and `cats.data.Cokleisli`(wrapping an `F[A] => B`). These type constructors all have `Arrow` instances. An arrow `F[A, B]` can be thought of as representing a computation from `A` to `B` with some context, just like a functor/applicative/monad `F[A]` represents a value `A` with some context.
Having an `Arrow` instance for a type constructor `F[_, _]` means that an `F[_, _]` can be composed and combined with other `F[_, _]`s. You will be able to do things like:
+
- Lifting a function `ab: A => B` into arrow `F[A, B]` with `Arrow[F].lift(ab)`. If `F` is `Function1` then `A => B` is the same as `F[A, B]` so `lift` is just the identity function.
- Composing `fab: F[A, B]` and `fbc: F[B, C]` into `fac: F[A, C]` with `Arrow[F].compose(fbc, fab)`, or `fab >>> fbc`. If `F` is `Function1` then `>>>` becomes an alias for `andThen`.
- Taking two arrows `fab: F[A, B]` and `fcd: F[C, D]` and combining them into `F[(A, C), (B, D)]` with `fab.split(fcd)` or `fab *** fcd`. The resulting arrow takes two inputs and processes them with two arrows, one for each input.
@@ -25,7 +21,7 @@ Suppose we want to write a function `meanAndVar`, that takes a `List[Int]` and r
```scala mdoc:silent
import cats.arrow.Arrow
-import cats.implicits._
+import cats.syntax.all._
def combine[F[_, _]: Arrow, A, B, C](fab: F[A, B], fac: F[A, C]): F[A, (B, C)] =
Arrow[F].lift((a: A) => (a, a)) >>> (fab *** fac)
diff --git a/docs/src/main/mdoc/typeclasses/arrowchoice.md b/docs/typeclasses/arrowchoice.md
similarity index 88%
rename from docs/src/main/mdoc/typeclasses/arrowchoice.md
rename to docs/typeclasses/arrowchoice.md
index 79a92cbfb2..d72bff5e70 100644
--- a/docs/src/main/mdoc/typeclasses/arrowchoice.md
+++ b/docs/typeclasses/arrowchoice.md
@@ -1,13 +1,6 @@
----
-layout: docs
-title: "Arrow Choice"
-section: "typeclasses"
-source: "core/src/main/scala/cats/arrow/ArrowChoice.scala"
-scaladoc: "#cats.arrow.ArrowChoice"
----
+# Arrow Choice
-
-# `Choice`
+API Documentation: @:api(cats.arrow.Choice)
Usually we deal with function more often, we're so familiar with `A => B`.
@@ -19,7 +12,7 @@ This is exactly typeclass `Choice` provided, if we make `=>` more generic such a
```scala
trait Choice[F[_, _]] {
- def choice[A,B,C,D](fac: F[A, C], fbc: F[B, C]): F[Either[A, B], C]
+ def choice[A, B, C](fac: F[A, C], fbc: F[B, C]): F[Either[A, B], C]
}
```
@@ -30,7 +23,7 @@ A very useful case of `Choice` is middleware in HTTP server.
Take Http4s for example:
-HttpRoutes[F] in Http4s is defined as [Kleisli](https://typelevel.org/cats/datatypes/kleisli.html)
+`HttpRoutes[F]` in Http4s is defined as [Kleisli](../datatypes/kleisli.md)
```scala
type HttpRoutes[F[_]] = Kleisli[OptionT[F, *], Request[F], Response[F]]
@@ -74,7 +67,7 @@ Another example will be HTTP response handler.
val resp: IO[Either[Throwable, String]] = httpClient.expect[String](uri"https://google.com/").attempt
```
-`attempt` is syntax from [`MonadError`](https://typelevel.org/cats/api/cats/MonadError.html)
+`attempt` is syntax from [`MonadError`](applicativemonaderror.md)
When we need to handle error, without `Choice` the handler would be something like:
```scala
diff --git a/docs/typeclasses/bifoldable.md b/docs/typeclasses/bifoldable.md
new file mode 100644
index 0000000000..a1d1d319bf
--- /dev/null
+++ b/docs/typeclasses/bifoldable.md
@@ -0,0 +1,153 @@
+# Bifoldable
+
+API Documentation: @:api(cats.Bifoldable)
+
+`Bifoldable[F[_,_]]` instances identify data structures with two independent `Foldable` that fold to the same summary value.
+
+As a reminder `Foldable` is implemented in terms of `foldLeft` and `foldRight`; similarly `Bifoldable` is implemented in terms of:
+```scala
+ //eagerly performs a left-associative bi-fold over `fab`
+ def bifoldLeft[A, B, C](fab: F[A, B], c: C)(f: (C, A) => C, g: (C, B) => C): C
+
+ //lazily performs a right-associative bi-fold over `fab`
+ def bifoldRight[A, B, C](fab: F[A, B], c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C]
+```
+and by implementing those 2 methods you also get:
+```scala
+ def bifold[A, B](fab: F[A, B])(implicit A: Monoid[A], B: Monoid[B]): (A, B)
+
+ def bifoldMap[A, B, C](fab: F[A, B])(f: A => C, g: B => C)(implicit C: Monoid[C]): C
+```
+A lawful instance must have `bifoldLeft\Right` consistent with `bifoldMap`; left\right bi-folds based on associative
+functions should output similar results.
+
+## Either and Validated as Bifoldable
+
+Assume multiple input paths and system requests that end up as `Either[Exception, *]` or `Validated[Exception, *]`.
+The requirement is to track the amount of errors and store the content of valid requests.
+
+First add the implicits:
+```scala mdoc
+import cats._
+import cats.data._
+import cats.syntax.all._
+```
+
+then let's define a summary class capable of storing this info:
+```scala mdoc
+case class Report(entries: Chain[String], errors: Int) {
+ def withEntries(entry: String): Report =
+ this.copy(entries = entries :+ entry)
+
+ def withError: Report =
+ this.copy(errors = errors + 1)
+}
+```
+
+`Bifoldable` is useful to get a summary value from `F[_,_]` data types:
+```scala mdoc
+def update[F[_, _]: Bifoldable](current: Report)(result: F[Exception, String]): Report =
+ result.bifoldLeft(current)((acc, _) => acc.withError, (acc, user) => acc.withEntries(user))
+```
+
+Here is the system input:
+```scala mdoc
+val validated =
+ List(
+ Validated.valid[Exception, String]("valid request 1"),
+ Validated.valid[Exception, String]("valid request 2"),
+ Validated.invalid[Exception, String](new RuntimeException("Not a valid request"))
+ )
+
+val attempted =
+ List(
+ Either.right[Exception, String]("valid request 1"),
+ Either.right[Exception, String]("valid request 2"),
+ Either.left[Exception, String](new RuntimeException("Not a valid request"))
+ )
+```
+
+and bi-fold each value into the accumulator:
+```scala mdoc
+val empty = Report(Chain.empty, 0)
+
+validated
+ .foldl(empty)((acc, validation) => update(acc)(validation))
+
+attempted
+ .foldl(empty)((acc, attempt) => update(acc)(attempt))
+```
+
+## Tuple as Bifoldable
+
+Assume we have `(String, String, Int)` and to get our summary we need `_1` and `_3`.
+The existing implementations for `(*, *)`, `(T0, *, *)`, `(T0, T1, *, *)` .. aren't useful.
+
+Let's make a new `Bifoldable` instance:
+```scala mdoc
+implicit def bifoldableForTuple3[A0]: Bifoldable[(*, A0, *)] =
+ new Bifoldable[(*, A0, *)] {
+ def bifoldLeft[A, B, C](fa: (A, A0, B), c: C)(f: (C, A) => C, g: (C, B) => C): C =
+ g(f(c, fa._1), fa._3)
+
+ def bifoldRight[A, B, C](fa: (A, A0, B), c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] =
+ g(fa._3, f(fa._1, c))
+ }
+```
+As we were saying in the beginning a lawful `Bifoldable` should have `bifoldLeft\Right` consistent with `bifoldMap`.
+Let's check our instance:
+```scala mdoc
+//(name, age, occupation)
+val description = ("Niki", 22, "Developer")
+
+val expected =
+ Bifoldable[(*, Int, *)].bifoldMap(description)(s => s, s => s)
+
+val left =
+ Bifoldable[(*, Int, *)].bifoldLeft(description, Monoid[String].empty)(
+ (acc, s) => acc |+| s,
+ (acc, s) => acc |+| s
+ )
+
+val right =
+ Bifoldable[(*, Int, *)].bifoldRight(description, Eval.later(Monoid[String].empty))(
+ (s, acc) => acc.map(_ |+| s),
+ (s, acc) => acc.map(_ |+| s)
+ )
+
+left === expected
+right.value === expected
+```
+**NOTE:** This instance would not be lawful if `bifoldRight` in particular would use a different ordering.
+
+Going from right to left as opposed to left to right means:
+```scala mdoc
+ def bifoldRight[A, B, C](fa: (A, Int, B), c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] =
+ f(fa._1, g(fa._3, c))
+```
+and it would also reverse the output making the instance unlawful:
+```scala mdoc
+val reversedRight =
+ bifoldRight(description, Eval.later(Monoid[String].empty))(
+ (s, acc) => acc.map(_ |+| s),
+ (s, acc) => acc.map(_ |+| s)
+ )
+
+reversedRight.value === expected
+```
+
+## Bifoldable `compose`
+
+If `F[_,_]` and `G[_,_]` have `Bifoldable` instances then so does `F[G[_,_],G[_,_]]`.
+
+Examples for `(Either[*, *], Either[*, *])` and `((*, *), (*, *))`:
+```scala mdoc
+Bifoldable[(*, *)]
+ .compose(Bifoldable[(*, *)])
+ .bifoldLeft((("name1 ", 1000),("name2 ", 2000)), List.empty[String])((acc, name) => acc :+ name, (acc, _) => acc)
+
+Bifoldable[(*, *)]
+ .compose(Bifoldable[Either[*, *]])
+ .bifold((Left(1), Right(2)))
+```
+
diff --git a/docs/src/main/mdoc/typeclasses/bifunctor.md b/docs/typeclasses/bifunctor.md
similarity index 94%
rename from docs/src/main/mdoc/typeclasses/bifunctor.md
rename to docs/typeclasses/bifunctor.md
index 55b80a3ef0..4b9b415679 100644
--- a/docs/src/main/mdoc/typeclasses/bifunctor.md
+++ b/docs/typeclasses/bifunctor.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Bifunctor"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Bifunctor.scala"
-scaladoc: "#cats.Bifunctor"
----
# Bifunctor
+API Documentation: @:api(cats.Bifunctor)
+
`Bifunctor` takes two type parameters instead of one, and is a functor in both
of these parameters. It defines a function `bimap`, which allows for mapping over both
arguments at the same time. Its signature is as follows:
@@ -26,7 +21,7 @@ convert it to an UNIX timestamp.
```scala mdoc:silent
import cats._
-import cats.implicits._
+import cats.syntax.all._
import java.time._
case class DomainError(message: String)
diff --git a/docs/typeclasses/bimonad.md b/docs/typeclasses/bimonad.md
new file mode 100644
index 0000000000..b8423b6819
--- /dev/null
+++ b/docs/typeclasses/bimonad.md
@@ -0,0 +1,80 @@
+# Bimonad
+
+API Documentation: @:api(cats.Bimonad)
+
+The `Bimonad` trait directly extends `Monad` and `Comonad` without introducing new methods. `Bimonad` is
+different from other `Bi` typeclasses like `Bifunctor`, `Bifoldable` or `Bitraverse` where the prefix describes
+a `F[_, _]`. The `Bimonad` is a `F[_]` and the `Bi` prefix has a different meaning here: it's both a `Monad` and a `Comonad`.
+Keep in mind `Bimonad` has its own added laws so something that is both monadic
+and comonadic may not necessarily be a lawful `Bimonad`.
+
+If you use `Bimonad` as a convenience type such that:
+```scala
+def f[T[_]: Monad: Comonad, S](fa: T[S]): S
+```
+is re-written to:
+```scala
+def f[T[_]: Bimonad, S](fa: T[S]): S
+```
+then `T[_]` also needs to respect an extra set of laws.
+
+### NonEmptyList as a Bimonad
+`NonEmptyList[_]` is a lawful `Bimonad` so you can chain computations (like a `Monad`) and `extract` the result at the end (like a `Comonad`).
+
+Here is a possible implementation:
+```scala mdoc
+import cats._
+import cats.data._
+import cats.syntax.all._
+
+implicit val nelBimonad: Bimonad[NonEmptyList] =
+ new Bimonad[NonEmptyList] {
+
+ // in order to have a lawful bimonad `pure` and `extract` need to respect: `nelBimonad.extract(nelBimonad.pure(a)) <-> a`
+ override def pure[A](a: A): NonEmptyList[A] =
+ NonEmptyList.one(a)
+
+ override def extract[A](fa: NonEmptyList[A]): A =
+ fa.head
+
+ // use coflatMap from NonEmptyList
+ override def coflatMap[A, B](fa: NonEmptyList[A])(f: NonEmptyList[A] => B): NonEmptyList[B] =
+ fa.coflatMap(f)
+
+ // use flatMap from NonEmptyList
+ override def flatMap[A, B](fa: NonEmptyList[A])(f: A => NonEmptyList[B]): NonEmptyList[B] =
+ fa.flatMap(f)
+
+ // the tailRecM implementation is not the subject of this material
+ // as an exercise try to implement it yourself
+ override def tailRecM[A, B](a: A)(fn: A => NonEmptyList[Either[A, B]]): NonEmptyList[B] =
+ ???
+ }
+```
+
+Note the equivalence:
+```scala mdoc
+nelBimonad.pure(true).extract === NonEmptyList.one(true).head
+```
+
+Using generic bimonad syntax we could define a function that appends and extracts a configuration:
+```scala mdoc
+def make[T[_]: Bimonad](config: T[String]): String =
+ config
+ .flatMap(c => Bimonad[T].pure(c + " with option A"))
+ .flatMap(c => Bimonad[T].pure(c + " with option B"))
+ .flatMap(c => Bimonad[T].pure(c + " with option C"))
+ .extract
+```
+
+This works with one element non-empty lists:
+```scala mdoc
+make(NonEmptyList.one("config"))
+```
+
+`Function0[_]` and `Eval[_]` are also lawful bimonads so the following calls are also valid:
+```scala mdoc
+make(() => "config")
+
+make(Eval.later("config"))
+```
diff --git a/docs/src/main/mdoc/typeclasses/comonad.md b/docs/typeclasses/comonad.md
similarity index 93%
rename from docs/src/main/mdoc/typeclasses/comonad.md
rename to docs/typeclasses/comonad.md
index 174808afba..279997bf29 100644
--- a/docs/src/main/mdoc/typeclasses/comonad.md
+++ b/docs/typeclasses/comonad.md
@@ -1,13 +1,8 @@
----
-layout: docs
-title: "Comonad"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Comonad.scala"
-scaladoc: "#cats.Comonad"
----
# Comonad
-`Comonad` is a `Functor` and provides duals of the [`Monad`](monad.html) `pure`
+API Documentation: @:api(cats.Comonad)
+
+`Comonad` is a `Functor` and provides duals of the [`Monad`](monad.md) `pure`
and `flatMap` functions. A dual to a function has the same types but the
direction of the arrows are reversed. Whether or not that is useful, or even possible,
depends on the particular type. For a more formal definition of duality, please
@@ -33,7 +28,7 @@ First some imports.
```scala mdoc:silent
import cats._
import cats.data._
-import cats.implicits._
+import cats.syntax.all._
import cats.instances.list._
```
diff --git a/docs/src/main/mdoc/typeclasses/contravariant.md b/docs/typeclasses/contravariant.md
similarity index 88%
rename from docs/src/main/mdoc/typeclasses/contravariant.md
rename to docs/typeclasses/contravariant.md
index 73678c17ff..3f14c17d93 100644
--- a/docs/src/main/mdoc/typeclasses/contravariant.md
+++ b/docs/typeclasses/contravariant.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Contravariant"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Contravariant.scala"
-scaladoc: "#cats.Contravariant"
----
# Contravariant
+API Documentation: @:api(cats.Contravariant)
+
The `Contravariant` type class is for functors that define a `contramap`
function with the following type:
@@ -14,13 +9,13 @@ function with the following type:
def contramap[A, B](fa: F[A])(f: B => A): F[B]
```
-It looks like regular (also called `Covariant`) [`Functor`](functor.html)'s `map`,
+It looks like regular (also called `Covariant`) [`Functor`](functor.md)'s `map`,
but with the `f` transformation reversed.
Generally speaking, if you have some context `F[A]` for type `A`,
and you can get an `A` value out of a `B` value — `Contravariant` allows you to get the `F[B]` context for `B`.
-Examples of `Contravariant` instances are [`Show`](show.html) and `scala.math.Ordering` (along with `cats.kernel.Order`).
+Examples of `Contravariant` instances are [`Show`](show.md) and `scala.math.Ordering` (along with `cats.kernel.Order`).
## Contravariant instance for Show.
@@ -29,7 +24,7 @@ Say we have a class `Money` with a `Show` instance, and a `Salary` class:
```scala mdoc:silent
import cats._
-import cats.implicits._
+import cats.syntax.all._
case class Money(amount: Int)
case class Salary(size: Money)
diff --git a/docs/src/main/mdoc/typeclasses/contravariantmonoidal.md b/docs/typeclasses/contravariantmonoidal.md
similarity index 89%
rename from docs/src/main/mdoc/typeclasses/contravariantmonoidal.md
rename to docs/typeclasses/contravariantmonoidal.md
index cae9d0ea20..350936e863 100644
--- a/docs/src/main/mdoc/typeclasses/contravariantmonoidal.md
+++ b/docs/typeclasses/contravariantmonoidal.md
@@ -1,13 +1,8 @@
----
-layout: docs
-title: "Contravariant Monoidal"
-section: "typeclasses"
-source: "core/src/main/scala/cats/ContravariantMonoidal.scala"
-scaladoc: "#cats.ContravariantMonoidal"
----
# Contravariant Monoidal
-The `ContravariantMonoidal` type class is for [`Contravariant`](contravariant.html) functors that can define a
+API Documentation: @:api(cats.ContravariantMonoidal)
+
+The `ContravariantMonoidal` type class is for [`Contravariant`](contravariant.md) functors that can define a
`product` function and a `unit` function.
```scala mdoc:silent
@@ -31,7 +26,7 @@ Basically, if you have two contexts `F[B]` and `F[C]` for types
from a type `A`, then `ContravariantMonoidal` allows you to obtain
a context `F[A]` for the type `A`.
-Examples of `ContravariantMonoidal` instances are [`Eq`](eq.html) and [`Const`](../datatypes/const.html),
+Examples of `ContravariantMonoidal` instances are [`Eq`](eq.md) and [`Const`](../datatypes/const.md),
but there are also interesting instances for other types.
## Predicates Have `ContravariantMonoidal`
@@ -41,7 +36,7 @@ An example application would be the case of predicates. Consider the type,
```scala mdoc:silent:reset
import cats._
-import cats.implicits._
+import cats.syntax.all._
case class Predicate[A](run: A => Boolean)
```
diff --git a/docs/typeclasses/directory.conf b/docs/typeclasses/directory.conf
new file mode 100644
index 0000000000..08270eb62b
--- /dev/null
+++ b/docs/typeclasses/directory.conf
@@ -0,0 +1,31 @@
+laika.title = Type Classes
+laika.navigationOrder = [
+ alternative.md
+ applicative.md
+ applicativemonaderror.md
+ applicativetraverse.md
+ arrow.md
+ arrowchoice.md
+ bifoldable.md
+ bifunctor.md
+ bimonad.md
+ comonad.md
+ contravariant.md
+ contravariantmonoidal.md
+ eq.md
+ foldable.md
+ functor.md
+ invariant.md
+ invariantmonoidal.md
+ lawtesting.md
+ monad.md
+ monoid.md
+ monoidk.md
+ nonemptytraverse.md
+ parallel.md
+ reducible.md
+ semigroup.md
+ semigroupk.md
+ show.md
+ traverse.md
+]
\ No newline at end of file
diff --git a/docs/src/main/mdoc/typeclasses/eq.md b/docs/typeclasses/eq.md
similarity index 90%
rename from docs/src/main/mdoc/typeclasses/eq.md
rename to docs/typeclasses/eq.md
index b97204d4f3..dc8aaaed8f 100644
--- a/docs/src/main/mdoc/typeclasses/eq.md
+++ b/docs/typeclasses/eq.md
@@ -1,13 +1,7 @@
----
-layout: docs
-title: "Eq"
-section: "typeclasses"
-source: "kernel/src/main/scala/cats/kernel/Eq.scala"
-scaladoc: "#cats.kernel.Eq"
----
-
# Eq
+API Documentation: @:api(cats.kernel.Eq)
+
Eq is an alternative to the standard Java `equals` method.
It is defined by the single method `eqv`:
@@ -40,7 +34,7 @@ eliminating these types of bugs altogether.
The `Eq` syntax package also offers some handy symbolic operators:
```scala mdoc
-import cats.implicits._
+import cats.syntax.all._
1 === 1
@@ -55,7 +49,7 @@ The first option using `Eq.fromUniversalEquals` only defers to `==` and works li
```scala mdoc
import cats.kernel.Eq
-import cats.implicits._
+import cats.syntax.all._
case class Foo(a: Int, b: String)
diff --git a/docs/src/main/mdoc/typeclasses/foldable.md b/docs/typeclasses/foldable.md
similarity index 84%
rename from docs/src/main/mdoc/typeclasses/foldable.md
rename to docs/typeclasses/foldable.md
index 87dc2d9b5b..888effd536 100644
--- a/docs/src/main/mdoc/typeclasses/foldable.md
+++ b/docs/typeclasses/foldable.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Foldable"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Foldable.scala"
-scaladoc: "#cats.Foldable"
----
# Foldable
+API Documentation: @:api(cats.Foldable)
+
Foldable type class instances can be defined for data structures that can be
folded to a summary value.
@@ -35,7 +30,7 @@ First some standard imports.
```scala mdoc:silent
import cats._
-import cats.implicits._
+import cats.syntax.all._
```
And examples.
@@ -109,29 +104,34 @@ which are lazy in their right hand argument to traverse the entire
structure unnecessarily. For example, if you have:
```scala mdoc
-val allFalse = Stream.continually(false)
+val allFalse = LazyList.continually(false)
```
-which is an infinite stream of `false` values, and if you wanted to
+which is an infinite list of `false` values, and if you wanted to
reduce this to a single false value using the logical and (`&&`). You
intuitively know that the result of this operation should be
-`false`. It is not necessary to consider the entire stream in order to
+`false`. It is not necessary to consider the entire list in order to
determine this result, you only need to consider the first
value. Using `foldRight` from the standard library *will* try to
-consider the entire stream, and thus will eventually cause a stack
-overflow:
+consider the entire list, and thus will eventually cause an out-of-memory error:
-```scala mdoc
-try {
- allFalse.foldRight(true)(_ && _)
-} catch {
- case e:StackOverflowError => println(e)
-}
+```scala
+// beware! throws OutOfMemoryError, which is irrecoverable
+allFalse.foldRight(true)(_ && _)
```
With the lazy `foldRight` on `Foldable`, the calculation terminates
after looking at only one value:
```scala mdoc
-Foldable[Stream].foldRight(allFalse, Eval.True)((a,b) => if (a) b else Eval.False).value
+Foldable[LazyList].foldRight(allFalse, Eval.True)((a,b) => if (a) b else Eval.False).value
+```
+
+Unfortunately, since `foldRight` is defined on many collections - this
+extension clashes with the operation defined in `Foldable`.
+To get past this and make sure you're getting the lazy `foldRight` defined
+in `Foldable`, there's an alias `foldr`:
+
+```scala mdoc
+allFalse.foldr(Eval.True)((a,b) => if (a) b else Eval.False).value
```
diff --git a/docs/src/main/mdoc/typeclasses/functor.md b/docs/typeclasses/functor.md
similarity index 95%
rename from docs/src/main/mdoc/typeclasses/functor.md
rename to docs/typeclasses/functor.md
index 3172caf9ac..646840f198 100644
--- a/docs/src/main/mdoc/typeclasses/functor.md
+++ b/docs/typeclasses/functor.md
@@ -1,11 +1,7 @@
----
-layout: docs
-title: "Functor"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Functor.scala"
-scaladoc: "#cats.Functor"
----
# Functor
+
+API Documentation: @:api(cats.Functor)
+
`Functor` is a type class that abstracts over type constructors that can be `map`'ed over. Examples of such
type constructors are `List`, `Option`, and `Future`.
@@ -66,7 +62,7 @@ Such composition can be achieved via the `Functor#compose` method.
```scala mdoc:reset:silent
import cats.Functor
-import cats.implicits._
+import cats.syntax.all._
```
```scala mdoc
@@ -95,7 +91,7 @@ We can make this nicer at the cost of boxing with the `Nested` data type.
```scala mdoc:silent
import cats.data.Nested
-import cats.implicits._
+import cats.syntax.all._
```
```scala mdoc
diff --git a/docs/src/main/mdoc/typeclasses/invariant.md b/docs/typeclasses/invariant.md
similarity index 87%
rename from docs/src/main/mdoc/typeclasses/invariant.md
rename to docs/typeclasses/invariant.md
index c9f7be4727..47fa66914b 100644
--- a/docs/src/main/mdoc/typeclasses/invariant.md
+++ b/docs/typeclasses/invariant.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Invariant"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Invariant.scala"
-scaladoc: "#cats.Invariant"
----
# Invariant
+API Documentation: @:api(cats.Invariant)
+
The `Invariant` type class is for functors that define an `imap`
function with the following type:
@@ -14,10 +9,10 @@ function with the following type:
def imap[A, B](fa: F[A])(f: A => B)(g: B => A): F[B]
```
-Every covariant (as well as [contravariant](contravariant.html)) functor gives rise to an invariant
+Every covariant (as well as [contravariant](contravariant.md)) functor gives rise to an invariant
functor, by ignoring the `g` (or in case of contravariance, `f`) function.
-Examples for instances of `Invariant` are [`Semigroup`](semigroup.html) and [`Monoid`](monoid.html), in
+Examples for instances of `Invariant` are [`Semigroup`](semigroup.md) and [`Monoid`](monoid.md), in
the following we will explain why this is the case using `Semigroup`, the
reasoning for `Monoid` is analogous.
@@ -29,7 +24,7 @@ timestamp. Let's say that we want to create a `Semigroup[Date]`, by
### Semigroup does not form a covariant functor
-If `Semigroup` had an instance for the standard covariant [`Functor`](functor.html)
+If `Semigroup` had an instance for the standard covariant [`Functor`](functor.md)
type class, we could use `map` to apply a function `longToDate`:
```scala mdoc:silent
@@ -47,7 +42,7 @@ like we can't have an `Functor` instance for `Semigroup`.
### Semigroup does not form a contravariant functor
On the other side, if `Semigroup` would form a *contravariant* functor
-by having an instance for [`Contravariant`](contravariant.html), we could make use of
+by having an instance for [`Contravariant`](contravariant.md), we could make use of
`contramap` to apply a function `dateToLong`:
```scala mdoc:silent
@@ -84,7 +79,7 @@ import java.util.Date
// import everything for simplicity:
import cats._
-import cats.implicits._
+import cats.syntax.all._
def longToDate: Long => Date = new Date(_)
def dateToLong: Date => Long = _.getTime
diff --git a/docs/src/main/mdoc/typeclasses/invariantmonoidal.md b/docs/typeclasses/invariantmonoidal.md
similarity index 86%
rename from docs/src/main/mdoc/typeclasses/invariantmonoidal.md
rename to docs/typeclasses/invariantmonoidal.md
index 712dfdbc01..68d32ea718 100644
--- a/docs/src/main/mdoc/typeclasses/invariantmonoidal.md
+++ b/docs/typeclasses/invariantmonoidal.md
@@ -1,13 +1,8 @@
----
-layout: docs
-title: "InvariantMonoidal"
-section: "typeclasses"
-source: "https://github.com/non/cats/blob/main/core/src/main/scala/cats/InvariantMonoidal.scala"
-scaladoc: "#cats.InvariantMonoidal"
----
# Invariant Monoidal
-`InvariantMonoidal` combines [`Invariant`](invariant.html) and `Semigroupal` with the addition of a `unit` methods, defined in isolation the `InvariantMonoidal` type class could be defined as follows:
+API Documentation: @:api(cats.InvariantMonoidal)
+
+`InvariantMonoidal` combines [`Invariant`](invariant.md) and `Semigroupal` with the addition of a `unit` methods, defined in isolation the `InvariantMonoidal` type class could be defined as follows:
```scala mdoc:compile-only
trait InvariantMonoidal[F[_]] {
@@ -17,36 +12,30 @@ trait InvariantMonoidal[F[_]] {
}
```
-Practical uses of `InvariantMonoidal` appear in the context of codecs, that is interfaces to capture both serialization and deserialization for a given format. Another notable examples is [`Semigroup`](semigroup.html).
+Practical uses of `InvariantMonoidal` appear in the context of codecs, that is interfaces to capture both serialization and deserialization for a given format. Another notable examples is [`Semigroup`](semigroup.md).
This tutorial first shows how `Semigroup` is `InvariantMonoidal`, and how this can be used create `Semigroup` instances by combining other `Semigroup` instances. Secondly, we present a complete example of `Codec` for the CSV format, and show how it is `InvariantMonoidal`. Lastly, we present an alternative definition of `InvariantMonoidal` as a generalization of `Invariant`, and show that both definitions are equivalent.
# `Semigroup` is `InvariantMonoidal`
-As explained in the [`Invariant` tutorial](invariant.html), `Semigroup` forms an invariant functor. Indeed, given a `Semigroup[A]` and two functions `A => B` and `B => A`, one can construct a `Semigroup[B]` by transforming two values from type `B` to type `A`, combining these using the `Semigroup[A]`, and transforming the result back to type `B`. Thus to define an `InvariantMonoidal[Semigroup]` we need implementations for `unit` and `product`.
+As explained in the [`Invariant` tutorial](invariant.md), `Semigroup` forms an invariant functor. Indeed, given a `Semigroup[A]` and two functions `A => B` and `B => A`, one can construct a `Semigroup[B]` by transforming two values from type `B` to type `A`, combining these using the `Semigroup[A]`, and transforming the result back to type `B`. Thus to define an `InvariantMonoidal[Semigroup]` we need implementations for `unit` and `product`.
To construct a `Semigroup` from a single value, we can define a trivial `Semigroup` with a combine that always outputs the given value. A `Semigroup[(A, B)]` can be obtained from two `Semigroup`s for type `A` and `B` by deconstructing two pairs into elements of type `A` and `B`, combining these element using their respective `Semigroup`s, and reconstructing a pair from the results:
```scala mdoc:silent
import cats.Semigroup
-def unit: Semigroup[Unit] =
- new Semigroup[Unit] {
- def combine(x: Unit, y: Unit): Unit = ()
- }
+def unit: Semigroup[Unit] = (_, _) => ()
-def product[A, B](fa: Semigroup[A], fb: Semigroup[B]): Semigroup[(A, B)] =
- new Semigroup[(A, B)] {
- def combine(x: (A, B), y: (A, B)): (A, B) = (x, y) match {
- case ((xa, xb), (ya, yb)) => fa.combine(xa, ya) -> fb.combine(xb, yb)
- }
- }
+def product[A, B](fa: Semigroup[A], fb: Semigroup[B]): Semigroup[(A, B)] = {
+ case ((xa, xb), (ya, yb)) => fa.combine(xa, ya) -> fb.combine(xb, yb)
+}
```
Given an instance of `InvariantMonoidal` for `Semigroup`, we are able to combine existing `Semigroup` instances to form a new `Semigroup` by using the `Semigroupal` syntax:
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
// Let's build a Semigroup for this case class
case class Foo(a: String, c: List[Double])
@@ -189,7 +178,7 @@ fooCodec.read(fooCodec.write(foo)) == ((Some(foo), List()))
# `InvariantMonoidal` as a generalization of `Invariant`
-To better understand the motivations behind the `InvariantMonoidal` type class, we show how one could naturally arrive to its definition by generalizing the concept of `Invariant` functor. This reflection is analogous to the one presented in [Free Applicative Functors by Paolo Capriotti](http://www.paolocapriotti.com/assets/applicative.pdf) to show how [`Applicative`](applicative.html) are a generalization of [`Functor`](functor.html).
+To better understand the motivations behind the `InvariantMonoidal` type class, we show how one could naturally arrive to its definition by generalizing the concept of `Invariant` functor. This reflection is analogous to the one presented in [Free Applicative Functors by Paolo Capriotti](http://www.paolocapriotti.com/assets/applicative.pdf) to show how [`Applicative`](applicative.md) are a generalization of [`Functor`](functor.md).
Given an `Invariant[F]` instance for a certain *context* `F[_]`, its `imap` method gives a way to lift two *unary* pure functions `A => B` and `B => A` into *contextualized* functions `F[A] => F[B]`. But what about functions of other arity?
diff --git a/docs/src/main/mdoc/typeclasses/lawtesting.md b/docs/typeclasses/lawtesting.md
similarity index 89%
rename from docs/src/main/mdoc/typeclasses/lawtesting.md
rename to docs/typeclasses/lawtesting.md
index e796b7f93e..f4a8ab68ab 100644
--- a/docs/src/main/mdoc/typeclasses/lawtesting.md
+++ b/docs/typeclasses/lawtesting.md
@@ -1,12 +1,6 @@
----
-layout: docs
-title: "Law Testing"
-section: "typeclasses"
----
-
# Law testing
-[Laws](https://typelevel.org/cats/typeclasses.html#laws) are an important part of cats.
+[Laws](../typeclasses.md#laws) are an important part of cats.
Cats uses [discipline](https://github.com/typelevel/discipline) to define type class laws and
the [ScalaCheck](https://github.com/rickynils/scalacheck) tests based on them.
@@ -15,12 +9,10 @@ To test type class laws from Cats against your instances, you need to add a `cat
## Getting started
First up, you will need to specify dependencies on `cats-laws` in your `build.sbt` file.
-To make things easier, we'll also include the `scalacheck-shapeless` library in this tutorial, so we don't have to manually write instances for ScalaCheck's `Arbitrary`.
```scala
libraryDependencies ++= Seq(
- "org.typelevel" %% "cats-laws" % "2.0.0" % Test,
- "com.github.alexarchambault" %% "scalacheck-shapeless_1.14" % "1.2.3" % Test
+ "org.typelevel" %% "cats-laws" % "@VERSION@" % Test,
)
```
@@ -64,7 +56,7 @@ For simplicity we'll just use `Eq.fromUniversalEquals`:
implicit def eqTree[A: Eq]: Eq[Tree[A]] = Eq.fromUniversalEquals
```
ScalaCheck requires `Arbitrary` instances for data types being tested. We have defined an `Arbitrary` instance for `Tree` here,
-but you won't need it if you import `org.scalacheck.ScalacheckShapeless._`).
+if you use Scala 2, you can avoid writing it manually with [scalacheck-shapeless](https://github.com/alexarchambault/scalacheck-shapeless).
```scala mdoc:silent
@@ -94,7 +86,7 @@ the `ScalaCheck` `Properties` provided by `cats-laws`.
The following example is for MUnit.
```scala mdoc
-import cats.implicits._
+import cats.syntax.all._
import cats.laws.discipline.FunctorTests
import munit.DisciplineSuite
import arbitraries._
@@ -134,14 +126,14 @@ So we have to import from there to test type classes like `Semigroup`, `Monoid`,
Let's test it out by defining a `Semigroup` instance for our `Tree` type.
```scala mdoc
-import cats.implicits._
+import cats.syntax.all._
implicit def semigroupTree[A: Semigroup]: Semigroup[Tree[A]] = new Semigroup[Tree[A]] {
def combine(x: Tree[A], y: Tree[A]) = (x, y) match {
case (Leaf, _) => Leaf
case (_, Leaf) => Leaf
case (Node(xp, xLeft, xRight), Node(yp, yLeft, yRight)) =>
- Node(xp |+| yp, xLeft |+| yLeft, xRight |+| yRight)
+ Node(xp |+| yp, combine(xLeft, yLeft), combine(xRight, yRight))
}
}
```
@@ -149,7 +141,7 @@ implicit def semigroupTree[A: Semigroup]: Semigroup[Tree[A]] = new Semigroup[Tre
Then we can add the Semigroup tests to our suite:
```scala mdoc:nest
-import cats.implicits._
+import cats.syntax.all._
import cats.kernel.laws.discipline.SemigroupTests
import cats.laws.discipline.FunctorTests
import munit.DisciplineSuite
diff --git a/docs/src/main/mdoc/typeclasses/monad.md b/docs/typeclasses/monad.md
similarity index 90%
rename from docs/src/main/mdoc/typeclasses/monad.md
rename to docs/typeclasses/monad.md
index 505cca2862..080f0a3986 100644
--- a/docs/src/main/mdoc/typeclasses/monad.md
+++ b/docs/typeclasses/monad.md
@@ -1,13 +1,8 @@
----
-layout: docs
-title: "Monad"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Monad.scala"
-scaladoc: "#cats.Monad"
----
# Monad
-`Monad` extends the [`Applicative`](applicative.html) type class with a
+API Documentation: @:api(cats.Monad)
+
+`Monad` extends the [`Applicative`](applicative.md) type class with a
new function `flatten`. Flatten takes a value in a nested context (eg.
`F[F[A]]` where F is the context) and "joins" the contexts together so
that we have a single context (ie. `F[A]`).
@@ -36,7 +31,7 @@ the identity function `x => x` (i.e. `flatMap(_)(x => x)`).
```scala mdoc:silent
import cats._
-implicit def optionMonad(implicit app: Applicative[Option]) =
+implicit def optionMonad(implicit app: Applicative[Option]): Monad[Option] =
new Monad[Option] {
// Define flatMap using Option's flatten method
override def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] =
@@ -93,7 +88,7 @@ and therefore stack safe implementation of `tailRecM`.
import cats.Monad
import scala.annotation.tailrec
-implicit val optionMonad = new Monad[Option] {
+implicit val optionMonad: Monad[Option] = new Monad[Option] {
def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = fa.flatMap(f)
def pure[A](a: A): Option[A] = Some(a)
@@ -106,7 +101,7 @@ implicit val optionMonad = new Monad[Option] {
}
```
-More discussion about `tailRecM` can be found in the [FAQ](../faq.html#tailrecm).
+More discussion about `tailRecM` can be found in the [FAQ](../faq.md#what-is-tailrecm).
### ifM
@@ -116,13 +111,13 @@ the results of earlier ones. This is embodied in `ifM`, which lifts an `if`
statement into the monadic context.
```scala mdoc
-import cats.implicits._
+import cats.syntax.all._
Monad[List].ifM(List(true, false, true))(ifTrue = List(1, 2), ifFalse = List(3, 4))
```
### Composition
-Unlike [`Functor`s](functor.html) and [`Applicative`s](applicative.html),
+Unlike [`Functor`s](functor.md) and [`Applicative`s](applicative.md),
not all `Monad`s compose. This means that even if `M[_]` and `N[_]` are
both `Monad`s, `M[N[_]]` is not guaranteed to be a `Monad`.
@@ -135,7 +130,7 @@ example).
```scala mdoc:silent:reset
import cats.Monad
-import cats.implicits._
+import cats.syntax.all._
case class OptionT[F[_], A](value: F[Option[A]])
@@ -163,7 +158,7 @@ implicit def optionTMonad[F[_]](implicit F: Monad[F]): Monad[OptionT[F, *]] = {
This sort of construction is called a monad transformer.
-Cats has an [`OptionT`](../datatypes/optiont.html) monad transformer, which adds a lot of useful functions to the simple implementation above.
+Cats has an [`OptionT`](../datatypes/optiont.md) monad transformer, which adds a lot of useful functions to the simple implementation above.
## FlatMap - a weakened Monad
A closely related type class is `FlatMap` which is identical to `Monad`, minus the `pure`
diff --git a/docs/src/main/mdoc/typeclasses/monoid.md b/docs/typeclasses/monoid.md
similarity index 90%
rename from docs/src/main/mdoc/typeclasses/monoid.md
rename to docs/typeclasses/monoid.md
index 5b84ec83fc..693a700e8c 100644
--- a/docs/src/main/mdoc/typeclasses/monoid.md
+++ b/docs/typeclasses/monoid.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Monoid"
-section: "typeclasses"
-source: "kernel/src/main/scala/cats/kernel/Monoid.scala"
-scaladoc: "#cats.kernel.Monoid"
----
# Monoid
+API Documentation: @:api(cats.kernel.Monoid)
+
`Monoid` extends the power of `Semigroup` by providing an additional `empty` value.
```scala mdoc:silent
@@ -58,7 +53,7 @@ def combineAll[A: Monoid](as: List[A]): A =
which can be used for any type that has a `Monoid` instance.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
```
```scala mdoc
@@ -89,10 +84,7 @@ final case class NonEmptyList[A](head: A, tail: List[A]) {
}
object NonEmptyList {
- implicit def nonEmptyListSemigroup[A]: Semigroup[NonEmptyList[A]] =
- new Semigroup[NonEmptyList[A]] {
- def combine(x: NonEmptyList[A], y: NonEmptyList[A]): NonEmptyList[A] = x ++ y
- }
+ implicit def nonEmptyListSemigroup[A]: Semigroup[NonEmptyList[A]] = _ ++ _
}
```
@@ -100,7 +92,7 @@ How then can we collapse a `List[NonEmptyList[A]]` ? For such types that only ha
lift into `Option` to get a `Monoid`.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
implicit def optionMonoid[A: Semigroup]: Monoid[Option[A]] = new Monoid[Option[A]] {
def empty: Option[A] = None
@@ -124,7 +116,7 @@ Thus:
```scala mdoc:reset:silent
import cats.Monoid
import cats.data.NonEmptyList
-import cats.implicits._
+import cats.syntax.all._
val list = List(NonEmptyList(1, List(2, 3)), NonEmptyList(4, List(5, 6)))
val lifted = list.map(nel => Option(nel))
diff --git a/docs/src/main/mdoc/typeclasses/monoidk.md b/docs/typeclasses/monoidk.md
similarity index 85%
rename from docs/src/main/mdoc/typeclasses/monoidk.md
rename to docs/typeclasses/monoidk.md
index cc7df1c0d2..6c15a01033 100644
--- a/docs/src/main/mdoc/typeclasses/monoidk.md
+++ b/docs/typeclasses/monoidk.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "MonoidK"
-section: "typeclasses"
-source: "core/src/main/scala/cats/MonoidK.scala"
-scaladoc: "#cats.MonoidK"
----
# MonoidK
+API Documentation: @:api(cats.MonoidK)
+
`MonoidK` is a universal monoid which operates on type constructors of one argument.
This type class is useful when its type parameter `F[_]` has a
@@ -32,7 +27,7 @@ First some imports:
```scala mdoc:silent
import cats.{Monoid, MonoidK}
-import cats.implicits._
+import cats.syntax.all._
```
Just like `Monoid[A]`, `MonoidK[F]` has an `empty` method, but it is parametrized on the type of the element contained in `F`:
@@ -58,4 +53,4 @@ MonoidK[List].combineK(List("hello", "world"), List("goodbye", "moon"))
MonoidK[List].combineK(List(1, 2), List(3, 4))
```
-`MonoidK` extends [`SemigroupK`](semigroupk.html), so take a look at the `SemigroupK` documentation for more examples.
+`MonoidK` extends [`SemigroupK`](semigroupk.md), so take a look at the `SemigroupK` documentation for more examples.
diff --git a/docs/src/main/mdoc/typeclasses/nonemptytraverse.md b/docs/typeclasses/nonemptytraverse.md
similarity index 76%
rename from docs/src/main/mdoc/typeclasses/nonemptytraverse.md
rename to docs/typeclasses/nonemptytraverse.md
index e5421251b4..2cafb09598 100644
--- a/docs/src/main/mdoc/typeclasses/nonemptytraverse.md
+++ b/docs/typeclasses/nonemptytraverse.md
@@ -1,14 +1,8 @@
----
-layout: docs
-title: "NonEmptyTraverse"
-section: "typeclasses"
-source: "core/src/main/scala/cats/NonEmptyTraverse.scala"
-scaladoc: "#cats.NonEmptyTraverse"
----
-
# NonEmptyTraverse
-`NonEmptyTraverse` is a non-empty version of the [Traverse](traverse.html) type class, just like [Reducible](reducible.html) is a non-empty version of [Foldable](foldable.html).
+API Documentation: @:api(cats.NonEmptyTraverse)
+
+`NonEmptyTraverse` is a non-empty version of the [Traverse](traverse.md) type class, just like [Reducible](reducible.md) is a non-empty version of [Foldable](foldable.md).
As such, it extends both `Reducible` and `Traverse` in the type class hierarchy.
It provides the `nonEmptyTraverse` and `nonEmptySequence` methods that require an instance of `Apply` instead of `Applicative`:
@@ -18,7 +12,7 @@ def nonEmptyTraverse[G[_]: Apply, A, B](fa: F[A])(f: A => G[B]): G[F[B]]
def nonEmptySequence[G[_]: Apply, A](fga: F[G[A]]): G[F[A]]
```
-In the [Applicative tutorial](applicative.html) we learned of `Apply` as a weakened `Applicative` lacking the `pure` method.
+In the [Applicative tutorial](applicative.md) we learned of `Apply` as a weakened `Applicative` lacking the `pure` method.
One example type lacking an `Applicative` instance is `Map[K, *]`, it's impossible to implement a `pure` method for it.
Knowing this, we can make use of `NonEmptyTraverse`, to traverse over a sequence of `Map`s.
@@ -26,13 +20,13 @@ One example application one could think of is, when we have a list of text snipp
count the occurrence of each word in each snippet and return all the common words and their occurrences in each snippet:
```scala mdoc
-import cats.implicits._
+import cats.syntax.all._
import cats.data.NonEmptyList
val snippets = NonEmptyList.of("What do you do", "What are you doing")
def countWords(text: String): Map[String, Int] =
- text.split(" ").groupBy(identity).mapValues(_.length)
+ text.split(" ").groupBy(identity).view.mapValues(_.length).toMap
snippets.nonEmptyTraverse(countWords)
```
diff --git a/docs/src/main/mdoc/typeclasses/parallel.dot b/docs/typeclasses/parallel.dot
similarity index 100%
rename from docs/src/main/mdoc/typeclasses/parallel.dot
rename to docs/typeclasses/parallel.dot
diff --git a/docs/src/main/mdoc/typeclasses/parallel.md b/docs/typeclasses/parallel.md
similarity index 93%
rename from docs/src/main/mdoc/typeclasses/parallel.md
rename to docs/typeclasses/parallel.md
index 0d7444d495..6a00397902 100644
--- a/docs/src/main/mdoc/typeclasses/parallel.md
+++ b/docs/typeclasses/parallel.md
@@ -1,17 +1,12 @@
----
-layout: docs
-title: "Parallel"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Parallel.scala"
-scaladoc: "#cats.Parallel"
----
# Parallel
+API Documentation: @:api(cats.Parallel)
+
When browsing the various `Monads` included in Cats,
you may have noticed that some of them have data types that are actually of the same structure,
but instead have instances of `Applicative`. E.g. `Either` and `Validated`.
-This is because defining a `Monad` instance for data types like `Validated` would be inconsistent with its error-accumulating behaviour.
+This is because defining a `Monad` instance for data types like `Validated` [would be inconsistent](../datatypes/validated.md#of-flatmaps-and-eithers) with its error-accumulating behaviour.
In short, `Monads` describe dependent computations and `Applicatives` describe independent computations.
Sometimes however, we want to use both in conjunction with each other.
@@ -20,7 +15,7 @@ Below is a short example of a situation where we might run into this.
For simplicity, we'll use `String` as our type to represent errors.
```scala mdoc
-import cats.implicits._
+import cats.syntax.all._
import cats.data._
case class Name(value: String)
@@ -76,7 +71,7 @@ Where `M[_]` has to have an instance of `Monad` and `F[_]` an instance of `Appli
![The `Parallel` typeclass transforms between `Monad` `M[_]` and `Applicative` `F[_]`.](../img/parallel.png)
-Recall that `~>` is just an alias for [`FunctionK`](../datatypes/functionk.html).
+Recall that `~>` is just an alias for [`FunctionK`](../datatypes/functionk.md).
This allows us to get rid of most of our boilerplate from earlier:
```scala mdoc:nest
@@ -119,4 +114,4 @@ An example for one of these is `ZipList`.
With instances of `NonEmptyParallel` it's not possible to use the `parTraverse` and `parSequence` functions,
but we can still use `parMapN` and also `parNonEmptyTraverse` and `parNonEmptySequence`,
-which are analogous to the functions defined on [`NonEmptyTraverse`](nonemptytraverse.html).
+which are analogous to the functions defined on [`NonEmptyTraverse`](nonemptytraverse.md).
diff --git a/docs/src/main/mdoc/typeclasses/reducible.md b/docs/typeclasses/reducible.md
similarity index 91%
rename from docs/src/main/mdoc/typeclasses/reducible.md
rename to docs/typeclasses/reducible.md
index 22575318cb..532f00ccb9 100644
--- a/docs/src/main/mdoc/typeclasses/reducible.md
+++ b/docs/typeclasses/reducible.md
@@ -1,13 +1,7 @@
----
-layout: docs
-title: "Reducible"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Reducible.scala"
-scaladoc: "#cats.Reducible"
----
-
# Reducible
+API Documentation: @:api(cats.Reducible)
+
`Reducible` extends the `Foldable` type class with additional `reduce` methods.
You may have come by one of the `reduce`, `reduceLeft` or `reduceOption` defined in Scala's standard collections.
@@ -31,7 +25,7 @@ First some standard imports.
```scala mdoc:silent
import cats._
import cats.data._
-import cats.implicits._
+import cats.syntax.all._
```
And examples.
@@ -46,7 +40,7 @@ Reducible[NonEmptyList].reduceLeftTo(NonEmptyList.of(1,2,3,4))(_.toString)((s,i)
Reducible[NonEmptyList].reduceRightTo(NonEmptyList.of(1,2,3,4))(_.toString)((i,s) => Later(s.value + i)).value
Reducible[NonEmptyList].nonEmptyIntercalate(NonEmptyList.of("a", "b", "c"), ", ")
-def countChars(s: String) = s.toCharArray.groupBy(identity).mapValues(_.length)
+def countChars(s: String) = s.toCharArray.groupBy(identity).view.mapValues(_.length).toMap
Reducible[NonEmptyList].nonEmptyTraverse_(NonEmptyList.of("Hello", "World"))(countChars)
Reducible[NonEmptyVector].nonEmptyTraverse_(NonEmptyVector.of("Hello", ""))(countChars)
diff --git a/docs/src/main/mdoc/typeclasses/semigroup.md b/docs/typeclasses/semigroup.md
similarity index 89%
rename from docs/src/main/mdoc/typeclasses/semigroup.md
rename to docs/typeclasses/semigroup.md
index a982df2854..e0e90a1c7e 100644
--- a/docs/src/main/mdoc/typeclasses/semigroup.md
+++ b/docs/typeclasses/semigroup.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Semigroup"
-section: "typeclasses"
-source: "kernel/src/main/scala/cats/kernel/Semigroup.scala"
-scaladoc: "#cats.kernel.Semigroup"
----
# Semigroup
+API Documentation: @:api(cats.kernel.Semigroup)
+
If a type `A` can form a `Semigroup` it has an **associative** binary operation.
```scala mdoc:silent
@@ -27,9 +22,7 @@ A common example of a semigroup is the type `Int` with the operation `+`.
```scala mdoc:reset:silent
import cats.Semigroup
-implicit val intAdditionSemigroup: Semigroup[Int] = new Semigroup[Int] {
- def combine(x: Int, y: Int): Int = x + y
-}
+implicit val intAdditionSemigroup: Semigroup[Int] = _ + _
val x = 1
val y = 2
@@ -47,7 +40,7 @@ Semigroup[Int].combine(Semigroup[Int].combine(x, y), z)
Infix syntax is also available for types that have a `Semigroup` instance.
```scala mdoc
-import cats.implicits._
+import cats.syntax.all._
1 |+| 2
```
@@ -56,7 +49,7 @@ A more compelling example which we'll see later in this tutorial is the `Semigro
for `Map`s.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
val map1 = Map("hello" -> 1, "world" -> 1)
val map2 = Map("hello" -> 2, "cats" -> 3)
@@ -74,7 +67,7 @@ Cats provides many `Semigroup` instances out of the box such as `Int` (`+`) and
```scala mdoc:reset:silent
import cats.Semigroup
-import cats.implicits._
+import cats.syntax.all._
```
```scala mdoc
@@ -108,7 +101,7 @@ type say, `Int` or `List[String]`, but we can write it once and for all for
any type with a `Semigroup` instance.
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
def optionCombine[A: Semigroup](a: A, opt: Option[A]): A =
opt.map(a |+| _).getOrElse(a)
@@ -176,7 +169,7 @@ def combineAll[A: Semigroup](as: List[A]): A =
```
`Semigroup` isn't powerful enough for us to implement this function - namely, it doesn't give us an identity
-or fallback value if the list is empty. We need a power expressive abstraction, which we can find in the
+or fallback value if the list is empty. We need a more powerfully expressive abstraction, which we can find in the
`Monoid` type class.
N.B.
diff --git a/docs/src/main/mdoc/typeclasses/semigroupk.md b/docs/typeclasses/semigroupk.md
similarity index 92%
rename from docs/src/main/mdoc/typeclasses/semigroupk.md
rename to docs/typeclasses/semigroupk.md
index ff5a027c5a..ff012fd8f4 100644
--- a/docs/src/main/mdoc/typeclasses/semigroupk.md
+++ b/docs/typeclasses/semigroupk.md
@@ -1,13 +1,8 @@
----
-layout: docs
-title: "SemigroupK"
-section: "typeclasses"
-source: "core/src/main/scala/cats/SemigroupK.scala"
-scaladoc: "#cats.SemigroupK"
----
# SemigroupK
-`SemigroupK` has a very similar structure to [`Semigroup`](semigroup.html), the difference
+API Documentation: @:api(cats.SemigroupK)
+
+`SemigroupK` has a very similar structure to [`Semigroup`](semigroup.md), the difference
is that `SemigroupK` operates on type constructors of one argument. So, for
example, whereas you can find a `Semigroup` for types which are fully
specified like `Int` or `List[Int]` or `Option[Int]`, you will find
@@ -23,7 +18,7 @@ First some imports.
```scala mdoc:silent
import cats._
-import cats.implicits._
+import cats.syntax.all._
```
For `List`, the `Semigroup` instance's `combine` operation and the `SemigroupK`
@@ -59,7 +54,7 @@ There is inline syntax available for both `Semigroup` and
from `SemigroupK` (called `Plus` in scalaz).
```scala mdoc:silent
-import cats.implicits._
+import cats.syntax.all._
val one = Option(1)
val two = Option(2)
diff --git a/docs/src/main/mdoc/typeclasses/show.md b/docs/typeclasses/show.md
similarity index 93%
rename from docs/src/main/mdoc/typeclasses/show.md
rename to docs/typeclasses/show.md
index c2b5eecf40..4cd26dd6f9 100644
--- a/docs/src/main/mdoc/typeclasses/show.md
+++ b/docs/typeclasses/show.md
@@ -1,12 +1,7 @@
----
-layout: docs
-title: "Show"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Show.scala"
-scaladoc: "#cats.Show"
----
# Show
+API Documentation: @:api(cats.Show)
+
Show is an alternative to the Java `toString` method.
It is defined by a single function `show`:
@@ -59,7 +54,7 @@ Cats also offers `Show` syntax to make working with it easier.
This includes the `show` method which can be called on anything with a `Show` instance in scope:
```scala mdoc
-import cats.implicits._
+import cats.syntax.all._
val john = Person("John", 31)
diff --git a/docs/src/main/mdoc/typeclasses/traverse.md b/docs/typeclasses/traverse.md
similarity index 96%
rename from docs/src/main/mdoc/typeclasses/traverse.md
rename to docs/typeclasses/traverse.md
index 0457ed0d23..9741463cda 100644
--- a/docs/src/main/mdoc/typeclasses/traverse.md
+++ b/docs/typeclasses/traverse.md
@@ -1,13 +1,7 @@
----
-layout: docs
-title: "Traverse"
-section: "typeclasses"
-source: "core/src/main/scala/cats/Traverse.scala"
-scaladoc: "#cats.Traverse"
----
-
# Traverse
+API Documentation: @:api(cats.Traverse)
+
In the `Applicative` tutorial we saw a more polymorphic version of the standard library
`Future.traverse` and `Future.sequence` functions, generalizing `Future` to be any
`F[_]` that's `Applicative`.
@@ -72,7 +66,7 @@ a `List[Option[A]]`. Since the values themselves are effects, traversing with `i
will turn the traversable "inside out."
```scala mdoc:reset:silent
-import cats.implicits._
+import cats.syntax.all._
```
```scala mdoc
@@ -160,7 +154,7 @@ def foldMap[F[_]: Traverse, A, B: Monoid](fa: F[A])(f: A => B): B =
Traverse[F].traverse[Const[B, *], A, B](fa)(a => Const(f(a))).getConst
```
-This works because `Const[B, *]` is an `Applicative` if `B` is a `Monoid`, as explained in [the documentation of `Const`](../datatypes/const.html#example-2-traverse).
+This works because `Const[B, *]` is an `Applicative` if `B` is a `Monoid`, as explained in [the documentation of `Const`](../datatypes/const.md#example-2-traverse).
## Further Reading
diff --git a/docs/src/main/mdoc/typelevelEcosystem.md b/docs/typelevelEcosystem.md
similarity index 98%
rename from docs/src/main/mdoc/typelevelEcosystem.md
rename to docs/typelevelEcosystem.md
index 6ac8f0710a..1fda503b8e 100644
--- a/docs/src/main/mdoc/typelevelEcosystem.md
+++ b/docs/typelevelEcosystem.md
@@ -1,20 +1,3 @@
----
-layout: page
-title: "Typelevel Ecosystem"
-section: ""
-position:
----
-
-
-[Cats]: https://typelevel.org/cats/ "Cats"
-[Fs2]: https://fs2.io "Fs2"
-[Kafka]: https://kafka.apache.org/ "Kafka"
-[Monix]: https://monix.io/ "Monix"
-[Mules]: https://github.com/davenverse/mules/ "Mules"
-[Cats Effect]: https://typelevel.org/cats-effect/ "Cats Effect"
-[Circe]: https://circe.github.io/circe/ "Circe"
-[Log4Cats]: https://typelevel.org/log4cats/ "Log4Cats"
-
# Typelevel Ecosystem #
By sharing the same set of type classes, instances and data types provided by Cats, projects can speak the same “Cats language”, and integrate with each other with ease.
@@ -46,7 +29,7 @@ Here you can find a comprehensive list of libraries and projects related to Type
| [circuit](https://davenverse.github.io/circuit/) | Functional Circuit Breaker implementation. |
| [ciris](https://cir.is/) | Lightweight, extensible, and validated configuration loading in Scala. |
| [console4cats](https://console4cats.profunktor.dev/) | Console I/O for [Cats Effect][Cats Effect]. |
-| [cormorant]https://davenverse.github.io/cormorant/) | CSV handling library for FP. |
+| [cormorant](https://davenverse.github.io/cormorant/) | CSV handling library for FP. |
| [coulomb-cats](https://github.com/erikerlandson/coulomb) | [Cats][Cats] typeclass instances for coulomb Quantity. |
| [decline](https://ben.kirw.in/decline/) | A composable command-line parser. |
| [doobie-pool](https://christopherdavenport.github.io/doobie-pool/) | Doobie Pooling Mechanism in Pure FP. |
@@ -55,15 +38,15 @@ Here you can find a comprehensive list of libraries and projects related to Type
| [dsl-domains-cats](https://github.com/ThoughtWorksInc/dsl-domains-cats) | The !-notation for creating [Cats][Cats] monadic expressions. |
| [dynamapath](https://christopherdavenport.github.io/dynamapath/) | Dynamic Path Parsing. |
| [eff](https://atnos-org.github.io/eff/) | Functional effects and effect handlers (alternative to monad transformers). |
-| [epimetheus-circuit](https://github.com/davenverse/epimetheus-circuit) | Prometeus Rejected Execution Metrics. |
-| [epimetheus-http4s](https://github.com/davenverse/epimetheus-http4s) | Prometeus Http4s Metrics Middleware and Push Gateway Support. |
-| [epimetheus-log4cats](https://github.com/davenverse/epimetheus-log4cats) | Prometeus Logging Metrics. |
-| [epimetheus-redis4cats](https://github.com/davenverse/epimetheus-redis4cats) | Prometeus Redis4cats Metrics. |
-| [epimetheus](https://davenverse.github.io/epimetheus/) | Prometeus Core Reperesentations. |
+| [epimetheus-circuit](https://github.com/davenverse/epimetheus-circuit) | Prometheus Rejected Execution Metrics. |
+| [epimetheus-http4s](https://github.com/davenverse/epimetheus-http4s) | Prometheus Http4s Metrics Middleware and Push Gateway Support. |
+| [epimetheus-log4cats](https://github.com/davenverse/epimetheus-log4cats) | Prometheus Logging Metrics. |
+| [epimetheus-redis4cats](https://github.com/davenverse/epimetheus-redis4cats) | Prometheus Redis4cats Metrics. |
+| [epimetheus](https://davenverse.github.io/epimetheus/) | Prometheus Core Representations. |
| [extruder](https://janstenpickle.github.io/extruder/) | Populate case classes from any data source. |
| [fastparse-cats](https://github.com/johnynek/fastparse-cats) | [Cats][Cats] Monad and Alternative instances for [fastparse](https://com-lihaoyi.github.io/fastparse/). |
| [fd4s/fs2-kafka](https://fd4s.github.io/fs2-kafka/) | Functional [Kafka][Kafka] Streams for Scala. |
-| [fetch](https://47degrees.github.io/fetch/) | Efficient data access to heterogeneous data sources. |
+| [fetch](https://xebia-functional.github.io/fetch/) | Efficient data access to heterogeneous data sources. |
| [finch](https://finagle.github.io/finch/) | Scala combinator api for building [finagle](https://twitter.github.io/finagle/) http services. |
| [fly4s](https://geirolz.github.io/fly4s/) | A lightweight, simple and functional wrapper for Flyway using [Cats Effect][Cats Effect]. |
| [frameless](https://github.com/typelevel/frameless) | Expressive types for [Spark](https://spark.apache.org/). |
@@ -87,6 +70,7 @@ Here you can find a comprehensive list of libraries and projects related to Type
| [fs2-rabbit](https://fs2-rabbit.profunktor.dev/) | [RabbitMQ](https://www.rabbitmq.com/) stream-based client built on top of [Fs2][Fs2] and [Cats Effect][Cats Effect]. |
| [fs2-reactive-streams](https://github.com/zainab-ali/fs2-reactive-streams) | A reactive streams implementation for [Fs2][Fs2]. |
| [fs2-ssh](https://github.com/precog/fs2-ssh) | A wrapper around Apache SSHD targeting [Cats Effect][Cats Effect] and [Fs2][Fs2]. |
+| [fs2-throttler](https://github.com/kovstas/fs2-throttler) | Throttling for fs2 based on the token bucket algorithm. |
| [fs2-zk](https://github.com/Spinoco/fs2-zk) | Simple Apache [Zookeeper](https://zookeeper.apache.org/) bindings for [Fs2][Fs2]. |
| [Fs2][Fs2] | Functional streams for Scala (streaming I/O library). |
| [fuuid-annotation](https://github.com/davenverse/fuuid-annotation) | Automatically create an inner Id tagged FUUID type with convenient methods for its creation. |
@@ -100,7 +84,7 @@ Here you can find a comprehensive list of libraries and projects related to Type
| [hammock](https://hammock.pepegar.com/) | Purely functional HTTP client. |
| [henkan](https://github.com/kailuowang/henkan) | Type safe conversion between case class instances with similar fields. |
| [http4s](https://http4s.org/) | Minimal, idiomatic Scala interface for HTTP services using [Fs2][Fs2]. |
-| [iota](https://github.com/frees-io/iota) | Fast [co]product types with a clean syntax. |
+| [iota](https://github.com/frees-io/iota) | Fast (co)product types with a clean syntax. |
| [itto-csv](https://github.com/gekomad/itto-csv) | Pure functional library for working with CSV. |
| [jms4s](https://fpinbo.dev/jms4s) | A functional wrapper for jms |
| [kafka4s](https://banno.github.io/kafka4s/) | Functional programming with [Kafka][Kafka] and Scala. |
@@ -178,18 +162,28 @@ Here you can find a comprehensive list of libraries and projects related to Type
| [whale-tail](https://github.com/davenverse/whale-tail) | Docker Daemon Integration. |
| | |
-Your project talks Cats too? [Submit a PR to add it here!](https://github.com/typelevel/cats/edit/main/docs/src/main/mdoc/typelevelEcosystem.md)
+Your project talks Cats too? [Submit a PR to add it here!](https://github.com/typelevel/cats/edit/main/docs/typelevelEcosystem.md)
-*The full-size [Cats logo](https://typelevel.org/cats/img/cats-logo.png) is available for use for Cats related projects, contents, souvenirs, etc.*
+*The full-size [Cats logo](img/cats-logo.png) is available for use for Cats related projects, contents, souvenirs, etc.*
-*We offer a [Cats Friendly Badge](https://typelevel.org/cats/img/cats-badge.svg) to let others know your project works with Cats!*
+*We offer a [Cats Friendly Badge](img/cats-badge.svg) to let others know your project works with Cats!*
-
+
Below are quick html and markdown snippets to use the badge in your own project.
```html
-
+
```
```markdown

```
+
+[Cats]: index.md "Cats"
+[Fs2]: https://fs2.io "Fs2"
+[Kafka]: https://kafka.apache.org/ "Kafka"
+[Monix]: https://monix.io/ "Monix"
+[Mules]: https://github.com/davenverse/mules/ "Mules"
+[Cats Effect]: https://typelevel.org/cats-effect/ "Cats Effect"
+[Circe]: https://circe.github.io/circe/ "Circe"
+[Log4Cats]: https://typelevel.org/log4cats/ "Log4Cats"
+
diff --git a/free/src/main/scala-2.12/cats/free/FreeStructuralInstances.scala b/free/src/main/scala-2.12/cats/free/FreeStructuralInstances.scala
index 0e90540945..8d80fa9393 100644
--- a/free/src/main/scala-2.12/cats/free/FreeStructuralInstances.scala
+++ b/free/src/main/scala-2.12/cats/free/FreeStructuralInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
private trait FreeStructuralInstances
diff --git a/free/src/main/scala-2.13+/cats/free/FreeStructuralInstances.scala b/free/src/main/scala-2.13+/cats/free/FreeStructuralInstances.scala
index b88676a2d4..94893de44a 100644
--- a/free/src/main/scala-2.13+/cats/free/FreeStructuralInstances.scala
+++ b/free/src/main/scala-2.13+/cats/free/FreeStructuralInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
@@ -33,13 +54,10 @@ private trait FreeStructuralInstances0 extends FreeStructuralInstances1 {
SF: Functor[S],
S: => Show[S[Free[S, A]]],
A: Show[A]
- ): Show[Free[S, A]] =
- Show.show { fsa =>
- fsa.resume match {
- case Right(a) => A.show(a)
- case Left(sfa) => S.show(sfa)
- }
- }
+ ): Show[Free[S, A]] = _.resume match {
+ case Right(a) => A.show(a)
+ case Left(sfa) => S.show(sfa)
+ }
implicit def catsFreeHashForFree[S[_], A](implicit
SF: Functor[S],
diff --git a/free/src/main/scala-2.x/cats/free/FreeFoldStep.scala b/free/src/main/scala-2/cats/free/FreeFoldStep.scala
similarity index 53%
rename from free/src/main/scala-2.x/cats/free/FreeFoldStep.scala
rename to free/src/main/scala-2/cats/free/FreeFoldStep.scala
index 4dfcf283e8..dccf6b246f 100644
--- a/free/src/main/scala-2.x/cats/free/FreeFoldStep.scala
+++ b/free/src/main/scala-2/cats/free/FreeFoldStep.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import Free.{FlatMapped, Pure, Suspend}
diff --git a/free/src/main/scala-3.x/cats/free/FreeFoldStep.scala b/free/src/main/scala-3/cats/free/FreeFoldStep.scala
similarity index 54%
rename from free/src/main/scala-3.x/cats/free/FreeFoldStep.scala
rename to free/src/main/scala-3/cats/free/FreeFoldStep.scala
index a5211f58c3..5aa6e44c8d 100644
--- a/free/src/main/scala-3.x/cats/free/FreeFoldStep.scala
+++ b/free/src/main/scala-3/cats/free/FreeFoldStep.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import Free.{FlatMapped, Pure, Suspend}
diff --git a/free/src/main/scala/cats/free/Cofree.scala b/free/src/main/scala/cats/free/Cofree.scala
index d540549186..8802848806 100644
--- a/free/src/main/scala/cats/free/Cofree.scala
+++ b/free/src/main/scala/cats/free/Cofree.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
@@ -177,7 +198,7 @@ private trait CofreeReducible[F[_]] extends Reducible[Cofree[F, *]] {
F.foldLeft(fa.tailForced, z(fa.head))((b, cof) => foldLeft(cof, b)(f))
override def reduceRightTo[A, B](fa: Cofree[F, A])(z: A => B)(f: (A, Eval[B]) => Eval[B]): Eval[B] =
- foldRight(fa, Eval.now((None: Option[B]))) { case (l, e) =>
+ foldRight(fa, Eval.now(None: Option[B])) { case (l, e) =>
e.flatMap {
case None => Eval.now(Some(z(l)))
case Some(r) => f(l, Eval.now(r)).map(Some(_))
diff --git a/free/src/main/scala/cats/free/ContravariantCoyoneda.scala b/free/src/main/scala/cats/free/ContravariantCoyoneda.scala
index b862facb44..e122fb283e 100644
--- a/free/src/main/scala/cats/free/ContravariantCoyoneda.scala
+++ b/free/src/main/scala/cats/free/ContravariantCoyoneda.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
diff --git a/free/src/main/scala/cats/free/Coyoneda.scala b/free/src/main/scala/cats/free/Coyoneda.scala
index 1645ae8285..49679c4e1f 100644
--- a/free/src/main/scala/cats/free/Coyoneda.scala
+++ b/free/src/main/scala/cats/free/Coyoneda.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
diff --git a/free/src/main/scala/cats/free/Free.scala b/free/src/main/scala/cats/free/Free.scala
index 32b6b7f520..7cd441df3e 100644
--- a/free/src/main/scala/cats/free/Free.scala
+++ b/free/src/main/scala/cats/free/Free.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
diff --git a/free/src/main/scala/cats/free/FreeApplicative.scala b/free/src/main/scala/cats/free/FreeApplicative.scala
index da06d61b4e..93e22a8304 100644
--- a/free/src/main/scala/cats/free/FreeApplicative.scala
+++ b/free/src/main/scala/cats/free/FreeApplicative.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
@@ -34,7 +55,7 @@ sealed abstract class FreeApplicative[F[_], A] extends Product with Serializable
case Pure(a) => fb.map(f(a, _))
case _ =>
fb match {
- case Pure(b) => Ap(Pure(f((_: A), b)), this)
+ case Pure(b) => Ap(Pure(f(_: A, b)), this)
case _ => Ap(Ap(Pure((a: A) => (b: B) => f(a, b)), this), fb)
}
}
@@ -59,7 +80,7 @@ sealed abstract class FreeApplicative[F[_], A] extends Product with Serializable
argsFLength -= 1
// rip off every `Ap` in `argF` in function position
- if (argF.isInstanceOf[Ap[F, _, _]]) {
+ if (argF.isInstanceOf[Ap[F, ?, ?]]) {
val lengthInitial = argsFLength
// reassociate the functions into a single fn,
// and move the arguments into argsF
@@ -68,7 +89,7 @@ sealed abstract class FreeApplicative[F[_], A] extends Product with Serializable
argsF ::= ap.fp
argsFLength += 1
argF = ap.fn.asInstanceOf[FA[F, Any]]
- argF.isInstanceOf[Ap[F, _, _]]
+ argF.isInstanceOf[Ap[F, ?, ?]]
}) ()
// consecutive `ap` calls have been queued as operations;
// argF is no longer an `Ap` node, so the entire topmost left-associated
diff --git a/free/src/main/scala/cats/free/FreeInvariantMonoidal.scala b/free/src/main/scala/cats/free/FreeInvariantMonoidal.scala
index 53f56231b3..a7fd4912c1 100644
--- a/free/src/main/scala/cats/free/FreeInvariantMonoidal.scala
+++ b/free/src/main/scala/cats/free/FreeInvariantMonoidal.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
diff --git a/free/src/main/scala/cats/free/FreeT.scala b/free/src/main/scala/cats/free/FreeT.scala
index f38c8f966e..1a24584a8e 100644
--- a/free/src/main/scala/cats/free/FreeT.scala
+++ b/free/src/main/scala/cats/free/FreeT.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
@@ -254,7 +275,7 @@ sealed abstract private[free] class FreeTInstances extends FreeTInstances0 {
E: MonadError[M, E]
): MonadError[FreeT[S, M, *], E] =
new MonadError[FreeT[S, M, *], E] with FreeTMonad[S, M] {
- override def M = E
+ override def M: Applicative[M] = E
override def handleErrorWith[A](fa: FreeT[S, M, A])(f: E => FreeT[S, M, A]) =
FreeT.liftT[S, M, FreeT[S, M, A]](E.handleErrorWith(fa.toM)(f.andThen(_.toM)))(M).flatMap(identity)
override def raiseError[A](e: E) =
@@ -273,7 +294,7 @@ sealed abstract private[free] class FreeTInstances extends FreeTInstances0 {
S: Functor[S]
): MonadError[FreeT[S, M, *], E] =
new MonadError[FreeT[S, M, *], E] with FreeTMonad[S, M] {
- override def M = E
+ override def M: Applicative[M] = E
private[this] val RealDefer = catsDeferForFreeT[S, M]
@@ -341,8 +362,8 @@ sealed abstract private[free] class FreeTInstances1 extends FreeTInstances2 {
sealed abstract private[free] class FreeTInstances2 extends FreeTInstances3 {
implicit def catsFreeAlternativeForFreeT[S[_], M[_]: Alternative: Monad]: Alternative[FreeT[S, M, *]] =
new Alternative[FreeT[S, M, *]] with FreeTMonad[S, M] with FreeTMonoidK[S, M] {
- override def M = Alternative[M]
- override def M1 = Alternative[M]
+ override def M: Applicative[M] = Alternative[M]
+ override def M1: MonoidK[M] = Alternative[M]
}
}
diff --git a/free/src/main/scala/cats/free/InvariantCoyoneda.scala b/free/src/main/scala/cats/free/InvariantCoyoneda.scala
index fc76efae95..a7d97f9501 100644
--- a/free/src/main/scala/cats/free/InvariantCoyoneda.scala
+++ b/free/src/main/scala/cats/free/InvariantCoyoneda.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
diff --git a/free/src/main/scala/cats/free/Trampoline.scala b/free/src/main/scala/cats/free/Trampoline.scala
index 16fbc7059a..540ad97415 100644
--- a/free/src/main/scala/cats/free/Trampoline.scala
+++ b/free/src/main/scala/cats/free/Trampoline.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
diff --git a/free/src/main/scala/cats/free/Yoneda.scala b/free/src/main/scala/cats/free/Yoneda.scala
index 472ceaf53f..b8d702ff8e 100644
--- a/free/src/main/scala/cats/free/Yoneda.scala
+++ b/free/src/main/scala/cats/free/Yoneda.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package free
diff --git a/free/src/main/scala/cats/free/package.scala b/free/src/main/scala/cats/free/package.scala
index fae8025e0b..8ab682bf35 100644
--- a/free/src/main/scala/cats/free/package.scala
+++ b/free/src/main/scala/cats/free/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package object free {
diff --git a/free/src/test/scala-2.13+/cats/free/FreeStructuralSuite.scala b/free/src/test/scala-2.13+/cats/free/FreeStructuralSuite.scala
index ec93681a7d..7aee33b776 100644
--- a/free/src/test/scala-2.13+/cats/free/FreeStructuralSuite.scala
+++ b/free/src/test/scala-2.13+/cats/free/FreeStructuralSuite.scala
@@ -1,7 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import cats.{Applicative, Eq, Eval, Functor, Show, Traverse}
-import cats.kernel.laws.discipline.{EqTests, PartialOrderTests}
+import cats.kernel.laws.discipline.{EqTests, HashTests, PartialOrderTests}
import cats.syntax.all._
import cats.tests.CatsSuite
@@ -25,8 +46,7 @@ class FreeStructuralSuite extends CatsSuite {
Show[Free[Option, Int]]
- // TODO HashLaws#sameAsUniversalHash is really dodgy
- // checkAll("Free[Option, Int]", HashTests[Free[Option, Int]].hash)
+ checkAll("Free[Option, Int]", HashTests[Free[Option, Int]].hash)
checkAll("Free[Option, Int]", PartialOrderTests[Free[Option, Int]].partialOrder)
checkAll("Free[ExprF, String]", EqTests[Free[ExprF, String]].eqv)
}
@@ -38,21 +58,16 @@ object FreeStructuralSuite {
sealed trait ExprF[A] extends Product with Serializable
object ExprF {
-
- implicit def eq[A: Eq]: Eq[ExprF[A]] =
- Eq.instance {
- case (Add(left1, right1), Add(left2, right2)) =>
- left1 === left2 && right1 === right2
-
- case (Neg(inner1), Neg(inner2)) =>
- inner1 === inner2
-
- case (Num(value1), Num(value2)) =>
- value1 === value2
-
- case (_, _) =>
- false
- }
+ implicit def eq[A: Eq]: Eq[ExprF[A]] = {
+ case (Add(left1, right1), Add(left2, right2)) =>
+ left1 === left2 && right1 === right2
+ case (Neg(inner1), Neg(inner2)) =>
+ inner1 === inner2
+ case (Num(value1), Num(value2)) =>
+ value1 === value2
+ case (_, _) =>
+ false
+ }
implicit def traverse: Traverse[ExprF] =
new Traverse[ExprF] {
diff --git a/free/src/test/scala/cats/free/CofreeSuite.scala b/free/src/test/scala/cats/free/CofreeSuite.scala
index 671a8dd5f9..dec6ed1ee0 100644
--- a/free/src/test/scala/cats/free/CofreeSuite.scala
+++ b/free/src/test/scala/cats/free/CofreeSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import cats.{~>, Comonad, Eval, Id, Reducible, Traverse}
@@ -11,6 +32,8 @@ import cats.tests.{CatsSuite, Spooky}
import org.scalacheck.{Arbitrary, Cogen, Gen}
import cats.syntax.eq._
+import scala.annotation.tailrec
+
class CofreeSuite extends CatsSuite {
import CofreeSuite._
@@ -155,18 +178,14 @@ sealed trait CofreeSuiteInstances {
type CofreeNel[A] = Cofree[Option, A]
type CofreeRoseTree[A] = Cofree[List, A]
- implicit def cofNelEq[A](implicit e: Eq[A]): Eq[CofreeNel[A]] =
- new Eq[CofreeNel[A]] {
- override def eqv(a: CofreeNel[A], b: CofreeNel[A]): Boolean = {
- def tr(a: CofreeNel[A], b: CofreeNel[A]): Boolean =
- (a.tailForced, b.tailForced) match {
- case (Some(at), Some(bt)) if e.eqv(a.head, b.head) => tr(at, bt)
- case (None, None) if e.eqv(a.head, b.head) => true
- case _ => false
- }
- tr(a, b)
+ implicit def cofNelEq[A](implicit e: Eq[A]): Eq[CofreeNel[A]] = new Eq[CofreeNel[A]] {
+ @tailrec def eqv(a: CofreeNel[A], b: CofreeNel[A]): Boolean =
+ (a.tailForced, b.tailForced) match {
+ case (Some(at), Some(bt)) if e.eqv(a.head, b.head) => eqv(at, bt)
+ case (None, None) if e.eqv(a.head, b.head) => true
+ case _ => false
}
- }
+ }
implicit def CofreeOptionCogen[A: Cogen]: Cogen[CofreeNel[A]] =
implicitly[Cogen[List[A]]].contramap[CofreeNel[A]](cofNelToNel(_).toList)
diff --git a/free/src/test/scala/cats/free/ContravariantCoyonedaSuite.scala b/free/src/test/scala/cats/free/ContravariantCoyonedaSuite.scala
index b462a7e824..047d0b3f2a 100644
--- a/free/src/test/scala/cats/free/ContravariantCoyonedaSuite.scala
+++ b/free/src/test/scala/cats/free/ContravariantCoyonedaSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import cats.{~>, Contravariant}
@@ -20,12 +41,10 @@ class ContravariantCoyonedaSuite extends CatsSuite {
// We can't really test that functions are equal but we can try it with a bunch of test data.
implicit def contravariantCoyonedaEq[A: Arbitrary, T](implicit eqft: Eq[T]): Eq[ContravariantCoyoneda[* => T, A]] =
- new Eq[ContravariantCoyoneda[* => T, A]] {
- def eqv(cca: ContravariantCoyoneda[* => T, A], ccb: ContravariantCoyoneda[* => T, A]): Boolean =
- Arbitrary.arbitrary[List[A]].sample.get.forall { a =>
- eqft.eqv(cca.run.apply(a), ccb.run.apply(a))
- }
- }
+ (cca, ccb) =>
+ Arbitrary.arbitrary[List[A]].sample.get.forall { a =>
+ eqft.eqv(cca.run.apply(a), ccb.run.apply(a))
+ }
// This instance cannot be summoned implicitly. This is not specific to contravariant coyoneda;
// it doesn't work for Functor[Coyoneda[* => String, *]] either.
diff --git a/free/src/test/scala/cats/free/CoyonedaSuite.scala b/free/src/test/scala/cats/free/CoyonedaSuite.scala
index 6686da46f6..3f8612779b 100644
--- a/free/src/test/scala/cats/free/CoyonedaSuite.scala
+++ b/free/src/test/scala/cats/free/CoyonedaSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import cats.Functor
@@ -15,9 +36,7 @@ class CoyonedaSuite extends CatsSuite {
Arbitrary(F.arbitrary.map(Coyoneda.lift))
implicit def coyonedaEq[F[_]: Functor, A](implicit FA: Eq[F[A]]): Eq[Coyoneda[F, A]] =
- new Eq[Coyoneda[F, A]] {
- def eqv(a: Coyoneda[F, A], b: Coyoneda[F, A]): Boolean = FA.eqv(a.run, b.run)
- }
+ Eq.by(_.run)
checkAll("Coyoneda[Option, *]", FunctorTests[Coyoneda[Option, *]].functor[Int, Int, Int])
checkAll("Functor[Coyoneda[Option, *]]", SerializableTests.serializable(Functor[Coyoneda[Option, *]]))
diff --git a/free/src/test/scala/cats/free/FreeApplicativeSuite.scala b/free/src/test/scala/cats/free/FreeApplicativeSuite.scala
index b4c12260a7..1525a830be 100644
--- a/free/src/test/scala/cats/free/FreeApplicativeSuite.scala
+++ b/free/src/test/scala/cats/free/FreeApplicativeSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import cats.{~>, Applicative, Apply, Id}
@@ -169,10 +190,7 @@ object FreeApplicativeSuite {
Arbitrary(freeGen[F, A](4))
implicit def freeApplicativeEq[S[_]: Applicative, A](implicit SA: Eq[S[A]]): Eq[FreeApplicative[S, A]] =
- new Eq[FreeApplicative[S, A]] {
- def eqv(a: FreeApplicative[S, A], b: FreeApplicative[S, A]): Boolean =
- SA.eqv(a.fold, b.fold)
- }
+ Eq.by(_.fold)
implicit def catsLawsArbitraryForListNatTrans: Arbitrary[List ~> List] =
Arbitrary(
diff --git a/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala b/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala
index d26223106d..c23ec66d33 100644
--- a/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala
+++ b/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import cats.{Id, InvariantMonoidal}
@@ -27,12 +48,7 @@ class FreeInvariantMonoidalSuite extends CatsSuite {
implicit def freeInvariantMonoidalEq[S[_]: InvariantMonoidal, A](implicit
SA: Eq[S[A]]
): Eq[FreeInvariantMonoidal[S, A]] =
- new Eq[FreeInvariantMonoidal[S, A]] {
- def eqv(a: FreeInvariantMonoidal[S, A], b: FreeInvariantMonoidal[S, A]): Boolean = {
- val nt = FunctionK.id[S]
- SA.eqv(a.foldMap(nt), b.foldMap(nt))
- }
- }
+ Eq.by(_.foldMap(FunctionK.id))
implicit val isoFreeBinCodec: Isomorphisms[FreeInvariantMonoidal[BinCodec, *]] =
Isomorphisms.invariant[FreeInvariantMonoidal[BinCodec, *]]
diff --git a/free/src/test/scala/cats/free/FreeSuite.scala b/free/src/test/scala/cats/free/FreeSuite.scala
index ed180dc7d1..7c1bb13d00 100644
--- a/free/src/test/scala/cats/free/FreeSuite.scala
+++ b/free/src/test/scala/cats/free/FreeSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import cats._
@@ -264,8 +285,5 @@ sealed trait FreeSuiteInstances1 {
Arbitrary(freeGen[F, A](4))
implicit def freeEq[S[_]: Monad, A](implicit SA: Eq[S[A]]): Eq[Free[S, A]] =
- new Eq[Free[S, A]] {
- def eqv(a: Free[S, A], b: Free[S, A]): Boolean =
- SA.eqv(a.runM(identity), b.runM(identity))
- }
+ Eq.by(_.runM(identity))
}
diff --git a/free/src/test/scala/cats/free/FreeTSuite.scala b/free/src/test/scala/cats/free/FreeTSuite.scala
index 88fdbedb03..fa1a538b1b 100644
--- a/free/src/test/scala/cats/free/FreeTSuite.scala
+++ b/free/src/test/scala/cats/free/FreeTSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import cats._
@@ -51,7 +72,7 @@ class FreeTSuite extends CatsSuite {
checkAll("FreeT[Option, Option, Int", DeferTests[FreeTOption].defer[Int])
test("FlatMap stack safety tested with 50k flatMaps") {
- val expected = Applicative[FreeTOption].pure(())
+ val expected = Applicative[FreeTOption].unit
val result =
Monad[FreeTOption].tailRecM(0)((i: Int) =>
if (i < 50000)
@@ -64,9 +85,9 @@ class FreeTSuite extends CatsSuite {
}
test("Stack safe with 50k left-associated flatMaps") {
- val expected = Applicative[FreeTOption].pure(())
+ val expected = Applicative[FreeTOption].unit
val result =
- (0 until 50000).foldLeft(Applicative[FreeTOption].pure(()))((fu, i) =>
+ (0 until 50000).foldLeft(Applicative[FreeTOption].unit)((fu, i) =>
fu.flatMap(u => Applicative[FreeTOption].pure(u))
)
@@ -74,7 +95,7 @@ class FreeTSuite extends CatsSuite {
}
test("Stack safe with flatMap followed by 50k maps") {
- val expected = Applicative[FreeTOption].pure(())
+ val expected = Applicative[FreeTOption].unit
val result =
(0 until 50000).foldLeft(().pure[FreeTOption].flatMap(_.pure[FreeTOption]))((fu, i) => fu.map(identity))
@@ -89,7 +110,7 @@ class FreeTSuite extends CatsSuite {
}
test("mapK stack-safety") {
- val a = (0 until 50000).foldLeft(Applicative[FreeTOption].pure(()))((fu, i) =>
+ val a = (0 until 50000).foldLeft(Applicative[FreeTOption].unit)((fu, i) =>
fu.flatMap(u => Applicative[FreeTOption].pure(u))
)
val b = a.mapK(FunctionK.id)
@@ -105,7 +126,7 @@ class FreeTSuite extends CatsSuite {
}
test("compile stack-safety") {
- val a = (0 until 50000).foldLeft(Applicative[FreeTOption].pure(()))((fu, i) =>
+ val a = (0 until 50000).foldLeft(Applicative[FreeTOption].unit)((fu, i) =>
fu.flatMap(u => Applicative[FreeTOption].pure(u))
)
val b = a.compile(FunctionK.id) // used to overflow
@@ -126,7 +147,7 @@ class FreeTSuite extends CatsSuite {
type F[A] = FreeT[Id, Option, A]
val F = MonadError[F, Unit]
- val eff = F.flatMap(F.pure(()))(_ => F.raiseError[String](()))
+ val eff = F.flatMap(F.unit)(_ => F.raiseError[String](()))
assert(F.attempt(eff).runM(Some(_)) === Some(Left(())))
}
@@ -281,14 +302,9 @@ trait FreeTSuiteInstances {
override def map[A, B](fa: JustFunctor[A])(f: A => B): JustFunctor[B] = JustFunctor(f(fa.a))
}
- implicit def freeTOptionEq[A](implicit A: Eq[A], OM: Monad[Option]): Eq[FreeTOption[A]] =
- new Eq[FreeTOption[A]] {
- def eqv(a: FreeTOption[A], b: FreeTOption[A]) = Eq[Option[A]].eqv(a.runM(identity), b.runM(identity))
- }
+ implicit def freeTOptionEq[A](implicit A: Eq[A]): Eq[FreeTOption[A]] =
+ Eq.by(_.runM(identity))
- implicit def freeTStateEq[A](implicit A: Eq[A], SM: Monad[IntState]): Eq[FreeTState[A]] =
- new Eq[FreeTState[A]] {
- def eqv(a: FreeTState[A], b: FreeTState[A]) =
- Eq[IntState[A]].eqv(a.runM(identity)(SM, SM), b.runM(identity)(SM, SM))
- }
+ implicit def freeTStateEq[A](implicit A: Eq[A]): Eq[FreeTState[A]] =
+ Eq.by(_.runM(identity))
}
diff --git a/free/src/test/scala/cats/free/InvariantCoyonedaSuite.scala b/free/src/test/scala/cats/free/InvariantCoyonedaSuite.scala
index 83b3a6c4ac..64fab709f5 100644
--- a/free/src/test/scala/cats/free/InvariantCoyonedaSuite.scala
+++ b/free/src/test/scala/cats/free/InvariantCoyonedaSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import cats.~>
@@ -29,12 +50,10 @@ class InvariantCoyonedaSuite extends CatsSuite {
// We can't really test that magmas are equal but we can try it with a bunch of test data.
implicit def invariantCoyonedaEq[A: Arbitrary: Eq]: Eq[InvariantCoyoneda[Magma, A]] =
- new Eq[InvariantCoyoneda[Magma, A]] {
- def eqv(cca: InvariantCoyoneda[Magma, A], ccb: InvariantCoyoneda[Magma, A]): Boolean =
- Arbitrary.arbitrary[List[(A, A)]].sample.get.forall { case (x, y) =>
- cca.run.apply(x, y) == ccb.run.apply(x, y)
- }
- }
+ (cca, ccb) =>
+ Arbitrary.arbitrary[List[(A, A)]].sample.get.forall { case (x, y) =>
+ cca.run.apply(x, y) == ccb.run.apply(x, y)
+ }
// Needed to help implicit resolution?
implicit val invariantCoyonedaMagma: Invariant[InvariantCoyoneda[Magma, *]] =
diff --git a/free/src/test/scala/cats/free/YonedaSuite.scala b/free/src/test/scala/cats/free/YonedaSuite.scala
index 21ee77352d..7944af57b2 100644
--- a/free/src/test/scala/cats/free/YonedaSuite.scala
+++ b/free/src/test/scala/cats/free/YonedaSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.free
import cats.Functor
@@ -14,9 +35,7 @@ class YonedaSuite extends CatsSuite {
Arbitrary(F.arbitrary.map(Yoneda(_)))
implicit def yonedaEq[F[_]: Functor, A](implicit FA: Eq[F[A]]): Eq[Yoneda[F, A]] =
- new Eq[Yoneda[F, A]] {
- def eqv(a: Yoneda[F, A], b: Yoneda[F, A]): Boolean = FA.eqv(a.run, b.run)
- }
+ Eq.by(_.run)
checkAll("Yoneda[Option, *]", FunctorTests[Yoneda[Option, *]].functor[Int, Int, Int])
checkAll("Functor[Yoneda[Option, *]]", SerializableTests.serializable(Functor[Yoneda[Option, *]]))
diff --git a/hydra-metrics-service.conf b/hydra-metrics-service.conf
deleted file mode 100644
index 4fe1e4025c..0000000000
--- a/hydra-metrics-service.conf
+++ /dev/null
@@ -1,17 +0,0 @@
-# mandatory: include the built-in settings tree
-include "application.conf"
-
-triplequote.dashboard.client {
- # Optional user ID override
- # metricsUserId = ${user.name}
-
- # Optional host ID (e.g. hostname)
- # metricsHostId = ""
-
- # Server address to push the metrics data
- serverUrl = "https://dashboard.triplequote.com/metrics"
-
- # Optional HTTP basic authentication
- clientUsername = ${?HYDRA_METRICS_USERNAME}
- clientPassword = ${?HYDRA_METRICS_PASSWORD}
-}
diff --git a/js/src/main/scala/cats/js/instances/future.scala b/js/src/main/scala/cats/js/instances/future.scala
deleted file mode 100644
index 5b13b9be58..0000000000
--- a/js/src/main/scala/cats/js/instances/future.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package cats
-package js
-package instances
-
-import scala.concurrent.Future
-import scala.concurrent.{ExecutionContext => E}
-import scala.concurrent.duration.FiniteDuration
-
-import cats.instances.FutureCoflatMap
-import cats.syntax.all._
-
-object future extends FutureInstances0
-
-object Await {
- def result[A](f: Future[A], atMost: FiniteDuration): A =
- f.value match {
- case Some(v) => v.get
- case None => throw new IllegalStateException()
- }
-}
-
-sealed private[instances] trait FutureInstances0 extends FutureInstances1 {
- def futureComonad(atMost: FiniteDuration)(implicit ec: E): Comonad[Future] =
- new FutureCoflatMap with Comonad[Future] {
- def extract[A](x: Future[A]): A =
- Await.result(x, atMost)
- }
-
- def futureOrder[A: Order](atMost: FiniteDuration)(implicit ec: E): Order[Future[A]] =
- new Order[Future[A]] {
- def compare(x: Future[A], y: Future[A]): Int =
- Await.result(x.zip(y).map { case (x, y) => x.compare(y) }, atMost)
- }
-}
-
-sealed private[instances] trait FutureInstances1 extends FutureInstances2 {
- def futurePartialOrder[A: PartialOrder](atMost: FiniteDuration)(implicit ec: E): PartialOrder[Future[A]] =
- new PartialOrder[Future[A]] {
- def partialCompare(x: Future[A], y: Future[A]): Double =
- Await.result(x.zip(y).map { case (x, y) => x.partialCompare(y) }, atMost)
- }
-
-}
-
-sealed private[instances] trait FutureInstances2 {
- def futureEq[A: Eq](atMost: FiniteDuration)(implicit ec: E): Eq[Future[A]] =
- new Eq[Future[A]] {
- def eqv(x: Future[A], y: Future[A]): Boolean =
- Await.result(x.zip(y).map { case (x, y) => x === y }, atMost)
- }
-}
diff --git a/kernel-laws/js/src/main/scala/cats/platform/Platform.scala b/kernel-laws/js/src/main/scala/cats/platform/Platform.scala
index 7a6c16c9e3..083e897ce9 100644
--- a/kernel-laws/js/src/main/scala/cats/platform/Platform.scala
+++ b/kernel-laws/js/src/main/scala/cats/platform/Platform.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.platform
private[cats] object Platform {
diff --git a/kernel-laws/jvm/src/main/scala/cats/platform/Platform.scala b/kernel-laws/jvm/src/main/scala/cats/platform/Platform.scala
index 7a208487e9..7387a5e307 100644
--- a/kernel-laws/jvm/src/main/scala/cats/platform/Platform.scala
+++ b/kernel-laws/jvm/src/main/scala/cats/platform/Platform.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.platform
private[cats] object Platform {
diff --git a/kernel-laws/native/src/main/scala/cats/platform/Platform.scala b/kernel-laws/native/src/main/scala/cats/platform/Platform.scala
index 699cdd6da2..67b4b5cb86 100644
--- a/kernel-laws/native/src/main/scala/cats/platform/Platform.scala
+++ b/kernel-laws/native/src/main/scala/cats/platform/Platform.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.platform
private[cats] object Platform {
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/BandLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/BandLaws.scala
index 167f2659ce..3cacd818bf 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/BandLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/BandLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.Band
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/BoundedLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/BoundedLaws.scala
index f3bf97acef..41bb49252f 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/BoundedLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/BoundedLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.{LowerBounded, PartialOrder, UpperBounded}
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/BoundedSemilatticeLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/BoundedSemilatticeLaws.scala
index 92963f3c24..456e782165 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/BoundedSemilatticeLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/BoundedSemilatticeLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.BoundedSemilattice
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeGroupLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeGroupLaws.scala
index 1f5735db4a..fa1019cf95 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeGroupLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeGroupLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeMonoidLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeMonoidLaws.scala
index 92e789794c..c3330d3c58 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeMonoidLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeMonoidLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.CommutativeMonoid
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeSemigroupLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeSemigroupLaws.scala
index 6e405649c1..81d83acbab 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeSemigroupLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/CommutativeSemigroupLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.CommutativeSemigroup
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/EnumerableLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/EnumerableLaws.scala
index e92037738b..e161339c6a 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/EnumerableLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/EnumerableLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package laws
@@ -73,15 +94,15 @@ trait BoundedEnumerableLaws[A]
extends PartialPreviousNextLaws[A]
with PartialPreviousBoundedLaws[A]
with PartialNextBoundedLaws[A] {
- override def B: LowerBounded[A] with UpperBounded[A]
+ override def B: LowerBounded[A] & UpperBounded[A]
}
object BoundedEnumerableLaws {
def apply[A](implicit ev: BoundedEnumerable[A]): BoundedEnumerableLaws[A] =
new BoundedEnumerableLaws[A] {
- val B: LowerBounded[A] with UpperBounded[A] = ev
+ val B: LowerBounded[A] & UpperBounded[A] = ev
val E = ev.order
- val N = ev
- val P = ev
+ val N: PartialNext[A] = ev
+ val P: PartialPrevious[A] = ev
}
}
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/EqLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/EqLaws.scala
index dab242124c..efc4b0365c 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/EqLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/EqLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.Eq
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/GroupLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/GroupLaws.scala
index b4ac324a73..c5f6e24e16 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/GroupLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/GroupLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/HashLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/HashLaws.scala
index 20fb31dd10..346d031b88 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/HashLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/HashLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package laws
@@ -9,10 +30,12 @@ trait HashLaws[A] extends EqLaws[A] {
def hashCompatibility(x: A, y: A): IsEq[Boolean] =
(!E.eqv(x, y) || (Hash.hash(x) == Hash.hash(y))) <-> true
+ @deprecated("This law is no longer enforced", "2.9.0")
def sameAsUniversalHash(x: A, y: A): IsEq[Boolean] =
((E.hash(x) == x.hashCode) && (Hash.fromUniversalHashCode[A].hash(x) == x.hashCode()) &&
(E.eqv(x, y) == Hash.fromUniversalHashCode[A].eqv(x, y))) <-> true
+ @deprecated("This law is no longer enforced", "2.9.0")
def sameAsScalaHashing(x: A, y: A, scalaHashing: Hashing[A]): IsEq[Boolean] =
((E.hash(x) == Hash.fromHashing(scalaHashing).hash(x)) &&
(E.eqv(x, y) == Hash.fromHashing(scalaHashing).eqv(x, y))) <-> true
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/IsEq.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/IsEq.scala
index 42d9031239..757035da14 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/IsEq.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/IsEq.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/MonoidLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/MonoidLaws.scala
index 8345e76044..93605a8589 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/MonoidLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/MonoidLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.{Eq, Monoid}
@@ -14,7 +35,7 @@ trait MonoidLaws[A] extends SemigroupLaws[A] {
def repeat0(x: A): IsEq[A] =
S.combineN(x, 0) <-> S.empty
- def collect0(x: A): IsEq[A] =
+ def collect0: IsEq[A] =
S.combineAll(Nil) <-> S.empty
def combineAll(xs: Vector[A]): IsEq[A] =
@@ -23,6 +44,8 @@ trait MonoidLaws[A] extends SemigroupLaws[A] {
def isId(x: A, eqv: Eq[A]): IsEq[Boolean] =
eqv.eqv(x, S.empty) <-> S.isEmpty(x)(eqv)
+ @deprecated("use `collect0` without parameters", "2.12.1")
+ def collect0(x: A): IsEq[A] = collect0
}
object MonoidLaws {
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/OrderLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/OrderLaws.scala
index 1595108dde..f332b7b825 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/OrderLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/OrderLaws.scala
@@ -1,8 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package laws
-import cats.kernel.Order
-
trait OrderLaws[A] extends PartialOrderLaws[A] {
implicit override def E: Order[A]
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/PartialOrderLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/PartialOrderLaws.scala
index 6f43250429..001be7298c 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/PartialOrderLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/PartialOrderLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.{Eq, PartialOrder}
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/SemigroupLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/SemigroupLaws.scala
index 92b6a082e0..622209132e 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/SemigroupLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/SemigroupLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.Semigroup
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/SemilatticeLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/SemilatticeLaws.scala
index 3490a2dddf..d229a67756 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/SemilatticeLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/SemilatticeLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.Semilattice
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/SerializableLaws.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/SerializableLaws.scala
index c6175eccef..bbd3e34c35 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/SerializableLaws.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/SerializableLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.platform.Platform
@@ -36,11 +57,11 @@ object SerializableLaws {
oos.close()
val bais = new ByteArrayInputStream(baos.toByteArray())
ois = new ObjectInputStream(bais)
- val a2 = ois.readObject()
+ val _ = ois.readObject()
ois.close()
Result(status = Proof)
} catch {
- case NonFatal(t) =>
+ case t if NonFatal(t) =>
Result(status = Exception(t))
} finally {
oos.close()
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BandTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BandTests.scala
index fd707966b1..8b363ff3bd 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BandTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BandTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BoundedSemilatticeTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BoundedSemilatticeTests.scala
index 80d646447a..2b96b835b2 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BoundedSemilatticeTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BoundedSemilatticeTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BoundedTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BoundedTests.scala
index 3058678aba..f95b9c0621 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BoundedTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/BoundedTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
@@ -10,12 +31,16 @@ import org.scalacheck.Prop.forAll
trait LowerBoundedTests[A] extends PartialOrderTests[A] {
def laws: LowerBoundedLaws[A]
- def lowerBounded(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ def lowerBounded(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A]): RuleSet =
new DefaultRuleSet(
"lowerBounded",
Some(partialOrder),
"bound is less than or equals" -> forAll(laws.boundLteqv _)
)
+
+ @deprecated("use `lowerBounded` without `Eq` parameters", "2.12.1")
+ def lowerBounded(arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ lowerBounded(arbA, arbF)
}
object LowerBoundedTests {
@@ -26,12 +51,16 @@ object LowerBoundedTests {
trait UpperBoundedTests[A] extends PartialOrderTests[A] {
def laws: UpperBoundedLaws[A]
- def upperBounded(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ def upperBounded(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A]): RuleSet =
new DefaultRuleSet(
"upperBounded",
Some(partialOrder),
"bound is greater than or equals" -> forAll(laws.boundGteqv _)
)
+
+ @deprecated("use `upperBounded` without `Eq` parameters", "2.12.1")
+ def upperBounded(arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ upperBounded(arbA, arbF)
}
object UpperBoundedTests {
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeGroupTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeGroupTests.scala
index f324fa4fe0..31f7d9eb5d 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeGroupTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeGroupTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeMonoidTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeMonoidTests.scala
index 95101a7900..bbfacc1f9a 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeMonoidTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeMonoidTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeSemigroupTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeSemigroupTests.scala
index c5430d1ea0..77822912cc 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeSemigroupTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/CommutativeSemigroupTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/EnumerableTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/EnumerableTests.scala
index d18a58ed75..471f89336c 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/EnumerableTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/EnumerableTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
@@ -11,7 +32,7 @@ trait PartialNextTests[A] extends PartialOrderTests[A] {
def laws: PartialNextLaws[A]
- def partialNext(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ def partialNext(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A]): RuleSet =
new DefaultRuleSet(
"partialNext",
Some(partialOrder),
@@ -19,13 +40,16 @@ trait PartialNextTests[A] extends PartialOrderTests[A] {
"forall a, b. if a < b. next(a) <= b" -> forAll(laws.nextOrderStrong _)
)
+ @deprecated("use `partialNext` without `Eq` parameters", "2.12.1")
+ def partialNext(arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ partialNext(arbA, arbF)
}
trait PartialPreviousTests[A] extends PartialOrderTests[A] {
def laws: PartialPreviousLaws[A]
- def partialPrevious(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ def partialPrevious(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A]): RuleSet =
new DefaultRuleSet(
"partialPrevious",
Some(partialOrder),
@@ -33,18 +57,16 @@ trait PartialPreviousTests[A] extends PartialOrderTests[A] {
"forall a, b. if a < b. next(a) <= b" -> forAll(laws.previousOrderStrong _)
)
+ @deprecated("use `partialPrevious` without `Eq` parameters", "2.12.1")
+ def partialPrevious(arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ partialPrevious(arbA, arbF)
}
trait BoundedEnumerableTests[A] extends OrderTests[A] with PartialNextTests[A] with PartialPreviousTests[A] {
def laws: BoundedEnumerableLaws[A]
- def boundedEnumerable(implicit
- arbA: Arbitrary[A],
- arbF: Arbitrary[A => A],
- eqOA: Eq[Option[A]],
- eqA: Eq[A]
- ): RuleSet =
+ def boundedEnumerable(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]]): RuleSet =
new RuleSet {
val name: String = "boundedEnumerable"
val bases: Seq[(String, RuleSet)] = Nil
@@ -57,6 +79,14 @@ trait BoundedEnumerableTests[A] extends OrderTests[A] with PartialNextTests[A] w
)
}
+ @deprecated("use `boundedEnumerable` without `Eq[A]` parameter", "2.12.1")
+ def boundedEnumerable(
+ arbA: Arbitrary[A],
+ arbF: Arbitrary[A => A],
+ eqOA: Eq[Option[A]],
+ eqA: Eq[A]
+ ): RuleSet =
+ boundedEnumerable(arbA, arbF, eqOA)
}
object BoundedEnumerableTests {
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/EqTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/EqTests.scala
index 83e6b42cf0..c474ea87ae 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/EqTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/EqTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/GroupTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/GroupTests.scala
index 2e7d9e1e38..8ac002d17e 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/GroupTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/GroupTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/HashTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/HashTests.scala
index 7655993068..89b3553267 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/HashTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/HashTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
@@ -13,15 +34,16 @@ trait HashTests[A] extends EqTests[A] {
def laws: HashLaws[A]
- def hash(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqA: Eq[A], hashA: Hashing[A]): RuleSet =
+ def hash(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A]): RuleSet =
new DefaultRuleSet(
"hash",
Some(eqv),
- "hash compatibility" -> forAll(laws.hashCompatibility _),
- "same as universal hash" -> forAll(laws.sameAsUniversalHash _),
- "same as scala hashing" -> forAll((x: A, y: A) => laws.sameAsScalaHashing(x, y, hashA))
+ "hash compatibility" -> forAll(laws.hashCompatibility _)
)
+ @deprecated("use `hash` without `Hashing` parameter", "2.12.1")
+ def hash(arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqA: Eq[A], hashA: Hashing[A]): RuleSet =
+ hash(arbA, arbF)
}
object HashTests {
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/MonoidTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/MonoidTests.scala
index 1436fee98f..1dbfa247cf 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/MonoidTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/MonoidTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
@@ -5,6 +26,7 @@ package discipline
import cats.kernel.instances.boolean._
import org.scalacheck.Arbitrary
+import org.scalacheck.Prop
import org.scalacheck.Prop.forAll
trait MonoidTests[A] extends SemigroupTests[A] {
@@ -18,7 +40,7 @@ trait MonoidTests[A] extends SemigroupTests[A] {
"left identity" -> forAll(laws.leftIdentity _),
"right identity" -> forAll(laws.rightIdentity _),
"combine all" -> forAll(laws.combineAll _),
- "collect0" -> forAll(laws.collect0 _),
+ "collect0" -> (laws.collect0: Prop),
"is id" -> forAll((a: A) => laws.isId(a, eqA)),
"repeat0" -> forAll(laws.repeat0 _)
)
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/OrderTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/OrderTests.scala
index 58c7857f30..017f501dc4 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/OrderTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/OrderTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
@@ -11,7 +32,7 @@ trait OrderTests[A] extends PartialOrderTests[A] {
def laws: OrderLaws[A]
- def order(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ def order(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A]): RuleSet =
new DefaultRuleSet(
"order",
Some(partialOrder),
@@ -21,6 +42,9 @@ trait OrderTests[A] extends PartialOrderTests[A] {
"min" -> forAll(laws.min _)
)
+ @deprecated("use `order` without `Eq` parameters", "2.12.1")
+ def order(arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ order(arbA, arbF)
}
object OrderTests {
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/PartialOrderTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/PartialOrderTests.scala
index 2b6d070afc..280522b233 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/PartialOrderTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/PartialOrderTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
@@ -11,7 +32,7 @@ trait PartialOrderTests[A] extends EqTests[A] {
def laws: PartialOrderLaws[A]
- def partialOrder(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ def partialOrder(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A]): RuleSet =
new DefaultRuleSet(
"partialOrder",
Some(eqv),
@@ -27,6 +48,9 @@ trait PartialOrderTests[A] extends EqTests[A] {
"pmin" -> forAll(laws.pmin _)
)
+ @deprecated("use `partialOrder` without `Eq` parameters", "2.12.1")
+ def partialOrder(arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqOA: Eq[Option[A]], eqA: Eq[A]): RuleSet =
+ partialOrder(arbA, arbF)
}
object PartialOrderTests {
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SemigroupTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SemigroupTests.scala
index 94ef8b79cf..b27fa70fcd 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SemigroupTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SemigroupTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SemilatticeTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SemilatticeTests.scala
index 89c3f4e918..e6e0ec7176 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SemilatticeTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SemilatticeTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package laws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SerializableTests.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SerializableTests.scala
index 8f71474d28..b0ef405d55 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SerializableTests.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/SerializableTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws.discipline
import cats.kernel.laws.SerializableLaws
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/package.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/package.scala
index 99fb11e50d..8e086ea3dd 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/package.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/discipline/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.laws
import cats.kernel.Eq
diff --git a/kernel-laws/shared/src/main/scala/cats/kernel/laws/package.scala b/kernel-laws/shared/src/main/scala/cats/kernel/laws/package.scala
index 6b2e9613ca..f1641f08ab 100644
--- a/kernel-laws/shared/src/main/scala/cats/kernel/laws/package.scala
+++ b/kernel-laws/shared/src/main/scala/cats/kernel/laws/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package object laws {
diff --git a/kernel-laws/shared/src/test/scala-2.12/cats/kernel/laws/ScalaVersionSpecificTests.scala b/kernel-laws/shared/src/test/scala-2.12/cats/kernel/laws/ScalaVersionSpecificTests.scala
index accbd6337b..fd01b6c89f 100644
--- a/kernel-laws/shared/src/test/scala-2.12/cats/kernel/laws/ScalaVersionSpecificTests.scala
+++ b/kernel-laws/shared/src/test/scala-2.12/cats/kernel/laws/ScalaVersionSpecificTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package laws
diff --git a/kernel-laws/shared/src/test/scala-2.13+/cats/kernel/laws/ScalaVersionSpecificTests.scala b/kernel-laws/shared/src/test/scala-2.13+/cats/kernel/laws/ScalaVersionSpecificTests.scala
index c9e6b3cdda..54433bcfef 100644
--- a/kernel-laws/shared/src/test/scala-2.13+/cats/kernel/laws/ScalaVersionSpecificTests.scala
+++ b/kernel-laws/shared/src/test/scala-2.13+/cats/kernel/laws/ScalaVersionSpecificTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package laws
diff --git a/kernel-laws/shared/src/test/scala/cats/kernel/laws/LawTests.scala b/kernel-laws/shared/src/test/scala/cats/kernel/laws/LawTests.scala
index 93fd7b39a6..b108d06f45 100644
--- a/kernel-laws/shared/src/test/scala/cats/kernel/laws/LawTests.scala
+++ b/kernel-laws/shared/src/test/scala/cats/kernel/laws/LawTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package laws
@@ -148,6 +169,9 @@ class Tests extends TestsConfig with DisciplineSuite {
checkAll("PartialOrder[Vector[HasPartialOrder[Int]]]", PartialOrderTests[Vector[HasPartialOrder[Int]]].partialOrder)
checkAll("PartialOrder[Stream[HasPartialOrder[Int]]]", PartialOrderTests[Stream[HasPartialOrder[Int]]].partialOrder)
checkAll("PartialOrder[Queue[HasPartialOrder[Int]]]", PartialOrderTests[Queue[HasPartialOrder[Int]]].partialOrder)
+ checkAll("PartialOrder[SortedMap[Int, HasPartialOrder[Int]]]",
+ PartialOrderTests[SortedMap[Int, HasPartialOrder[Int]]].partialOrder
+ )
checkAll("Semilattice.asMeetPartialOrder[Set[Int]]",
PartialOrderTests(Semilattice.asMeetPartialOrder[Set[Int]]).partialOrder
)
@@ -171,6 +195,7 @@ class Tests extends TestsConfig with DisciplineSuite {
checkAll("Order[Stream[Int]]", OrderTests[Stream[Int]].order)
checkAll("Order[Queue[Int]]", OrderTests[Queue[Int]].order)
checkAll("Order[SortedSet[String]", OrderTests[SortedSet[String]].order)
+ checkAll("Order[SortedMap[Int, String]]", OrderTests[SortedMap[Int, String]].order)
checkAll("fromOrdering[Int]", OrderTests(Order.fromOrdering[Int]).order)
checkAll("Order.reverse(Order[Int])", OrderTests(Order.reverse(Order[Int])).order)
checkAll("Order.reverse(Order.reverse(Order[Int]))", OrderTests(Order.reverse(Order.reverse(Order[Int]))).order)
@@ -328,14 +353,11 @@ class Tests extends TestsConfig with DisciplineSuite {
// Comparison related
// Something that can give NaN for test
- def subsetPartialOrder[A]: PartialOrder[Set[A]] =
- new PartialOrder[Set[A]] {
- def partialCompare(x: Set[A], y: Set[A]): Double =
- if (x == y) 0.0
- else if (x.subsetOf(y)) -1.0
- else if (y.subsetOf(x)) 1.0
- else Double.NaN
- }
+ def subsetPartialOrder[A]: PartialOrder[Set[A]] = (x, y) =>
+ if (x == y) 0.0
+ else if (x.subsetOf(y)) -1.0
+ else if (y.subsetOf(x)) 1.0
+ else Double.NaN
checkAll("subsetPartialOrder[Int]", PartialOrderTests(subsetPartialOrder[Int]).partialOrder)
@@ -400,9 +422,7 @@ class Tests extends TestsConfig with DisciplineSuite {
// esoteric machinery follows...
implicit lazy val band: Band[(Int, Int)] =
- new Band[(Int, Int)] {
- def combine(a: (Int, Int), b: (Int, Int)) = (a._1, b._2)
- }
+ Band.instance((a, b) => (a._1, b._2))
{
// In order to check the monoid laws for `Order[N]`, we need
@@ -438,17 +458,13 @@ class Tests extends TestsConfig with DisciplineSuite {
implicit val NOrderEq: Eq[Order[N]] = Eq.by { (order: Order[N]) =>
Vector.tabulate(nMax)(N).sorted(order.toOrdering)
}
- implicit val NEqEq: Eq[Eq[N]] = new Eq[Eq[N]] {
- def eqv(a: Eq[N], b: Eq[N]) =
- Iterator
- .tabulate(nMax)(N)
- .flatMap { x =>
- Iterator.tabulate(nMax)(N).map((x, _))
- }
- .forall { case (x, y) => a.eqv(x, y) == b.eqv(x, y) }
- }
+ implicit val NEqEq: Eq[Eq[N]] = (a, b) =>
+ Iterator
+ .tabulate(nMax)(N)
+ .flatMap(x => Iterator.tabulate(nMax)(N).map((x, _)))
+ .forall { case (x, y) => a.eqv(x, y) == b.eqv(x, y) }
- implicit val monoidOrderN: Monoid[Order[N]] with Band[Order[N]] = Order.whenEqualMonoid[N]
+ implicit val monoidOrderN: Monoid[Order[N]] & Band[Order[N]] = Order.whenEqualMonoid[N]
checkAll("Monoid[Order[N]]", MonoidTests[Order[N]].monoid)
checkAll("Band[Order[N]]", BandTests[Order[N]].band)
diff --git a/kernel/src/main/scala-2.12/cats/kernel/EnumerableCompat.scala b/kernel/src/main/scala-2.12/cats/kernel/EnumerableCompat.scala
index c604c892a5..3f86db3bd4 100644
--- a/kernel/src/main/scala-2.12/cats/kernel/EnumerableCompat.scala
+++ b/kernel/src/main/scala-2.12/cats/kernel/EnumerableCompat.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
diff --git a/kernel/src/main/scala-2.12/cats/kernel/ScalaVersionSpecificInstances.scala b/kernel/src/main/scala-2.12/cats/kernel/ScalaVersionSpecificInstances.scala
index 621365d5ee..0911f9b067 100644
--- a/kernel/src/main/scala-2.12/cats/kernel/ScalaVersionSpecificInstances.scala
+++ b/kernel/src/main/scala-2.12/cats/kernel/ScalaVersionSpecificInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
private[kernel] trait ScalaVersionSpecificOrderInstances extends ScalaVersionSpecificPartialOrderInstances {
diff --git a/kernel/src/main/scala-2.12/cats/kernel/compat/HashCompat.scala b/kernel/src/main/scala-2.12/cats/kernel/compat/HashCompat.scala
index 8fa7aa428a..411028fd07 100644
--- a/kernel/src/main/scala-2.12/cats/kernel/compat/HashCompat.scala
+++ b/kernel/src/main/scala-2.12/cats/kernel/compat/HashCompat.scala
@@ -1,10 +1,53 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package compat
+/* This file is derived in part from https://github.com/scala/scala/blob/v2.12.2/src/library/scala/util/hashing/MurmurHash3.scala
+ * Modified by Typelevel for redistribution in Cats.
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ * Scala
+ * Copyright (c) 2002-2022 EPFL
+ * Copyright (c) 2011-2022 Lightbend, Inc.
+ *
+ * Scala includes software developed at
+ * LAMP/EPFL (https://lamp.epfl.ch/) and
+ * Lightbend, Inc. (https://www.lightbend.com/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import scala.annotation.nowarn
+
private[kernel] class HashCompat {
// Adapted from scala.util.hashing.MurmurHash#productHash.
- private[kernel] def product1HashWithPrefix(_1Hash: Int, prefix: String): Int = {
+ private[kernel] def product1HashWithPrefix(_1Hash: Int, @nowarn("cat=unused") prefix: String): Int = {
import scala.util.hashing.MurmurHash3._
var h = productSeed
h = mix(h, _1Hash)
@@ -12,7 +55,7 @@ private[kernel] class HashCompat {
}
// Adapted from scala.util.hashing.MurmurHash#productHash.
- private[cats] def product2HashWithPrefix(_1Hash: Int, _2Hash: Int, prefix: String): Int = {
+ private[cats] def product2HashWithPrefix(_1Hash: Int, _2Hash: Int, @nowarn("cat=unused") prefix: String): Int = {
import scala.util.hashing.MurmurHash3._
var h = productSeed
h = mix(h, _1Hash)
diff --git a/kernel/src/main/scala-2.12/cats/kernel/compat/TraversableOnce.scala b/kernel/src/main/scala-2.12/cats/kernel/compat/TraversableOnce.scala
index 76c5924392..66c8fca968 100644
--- a/kernel/src/main/scala-2.12/cats/kernel/compat/TraversableOnce.scala
+++ b/kernel/src/main/scala-2.12/cats/kernel/compat/TraversableOnce.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package compat
diff --git a/kernel/src/main/scala-2.12/cats/kernel/compat/WrappedMutableMapBase.scala b/kernel/src/main/scala-2.12/cats/kernel/compat/WrappedMutableMapBase.scala
index df8330d7c1..ec8ed730ea 100644
--- a/kernel/src/main/scala-2.12/cats/kernel/compat/WrappedMutableMapBase.scala
+++ b/kernel/src/main/scala-2.12/cats/kernel/compat/WrappedMutableMapBase.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package compat
diff --git a/kernel/src/main/scala-2.12/cats/kernel/compat/scalaVersionSpecific.scala b/kernel/src/main/scala-2.12/cats/kernel/compat/scalaVersionSpecific.scala
index d5d8278240..ea473c1350 100644
--- a/kernel/src/main/scala-2.12/cats/kernel/compat/scalaVersionSpecific.scala
+++ b/kernel/src/main/scala-2.12/cats/kernel/compat/scalaVersionSpecific.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.compat
import scala.annotation.{Annotation, StaticAnnotation}
import scala.collection.{IterableLike, TraversableLike}
@@ -13,6 +34,8 @@ private[cats] object scalaVersionSpecific {
implicit class traversableOnceExtension[A](private val to: TraversableOnce[A]) extends AnyVal {
def iterator: Iterator[A] = to.toIterator
+
+ def knownSize: Int = -1
}
implicit class doubleExtension(private val double: Double) extends AnyVal {
diff --git a/kernel/src/main/scala-2.12/cats/kernel/instances/AllInstances.scala b/kernel/src/main/scala-2.12/cats/kernel/instances/AllInstances.scala
index 9b3496477e..8bc45b444e 100644
--- a/kernel/src/main/scala-2.12/cats/kernel/instances/AllInstances.scala
+++ b/kernel/src/main/scala-2.12/cats/kernel/instances/AllInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala-2.12/cats/kernel/instances/StreamInstances.scala b/kernel/src/main/scala-2.12/cats/kernel/instances/StreamInstances.scala
index 8fb9587f6c..c5e489d7cc 100644
--- a/kernel/src/main/scala-2.12/cats/kernel/instances/StreamInstances.scala
+++ b/kernel/src/main/scala-2.12/cats/kernel/instances/StreamInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/EnumerableCompat.scala b/kernel/src/main/scala-2.13+/cats/kernel/EnumerableCompat.scala
index ba2317cd14..8a782e5ae3 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/EnumerableCompat.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/EnumerableCompat.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/ScalaVersionSpecificInstances.scala b/kernel/src/main/scala-2.13+/cats/kernel/ScalaVersionSpecificInstances.scala
index d5ac6ea207..cd8bf437ce 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/ScalaVersionSpecificInstances.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/ScalaVersionSpecificInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.collection.immutable.ArraySeq
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/compat/HashCompat.scala b/kernel/src/main/scala-2.13+/cats/kernel/compat/HashCompat.scala
index 02a366c292..7ff34228c3 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/compat/HashCompat.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/compat/HashCompat.scala
@@ -1,7 +1,48 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
package compat
+/* This file is derived in part from https://github.com/scala/scala/blob/v2.13.0-RC1/src/library/scala/util/hashing/MurmurHash3.scala
+ * Modified by Typelevel for redistribution in Cats.
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ * Scala
+ * Copyright (c) 2002-2022 EPFL
+ * Copyright (c) 2011-2022 Lightbend, Inc.
+ *
+ * Scala includes software developed at
+ * LAMP/EPFL (https://lamp.epfl.ch/) and
+ * Lightbend, Inc. (https://www.lightbend.com/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
private[kernel] class HashCompat {
// Adapted from scala.util.hashing.MurmurHash#productHash.
private[kernel] def product1HashWithPrefix(_1Hash: Int, prefix: String): Int = {
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/compat/WrappedMutableMapBase.scala b/kernel/src/main/scala-2.13+/cats/kernel/compat/WrappedMutableMapBase.scala
index 425cf0c858..3180b7d55e 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/compat/WrappedMutableMapBase.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/compat/WrappedMutableMapBase.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package compat
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/compat/scalaVersionMoreSpecific.scala b/kernel/src/main/scala-2.13+/cats/kernel/compat/scalaVersionMoreSpecific.scala
index 5f8c6aec2a..3a2b365dca 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/compat/scalaVersionMoreSpecific.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/compat/scalaVersionMoreSpecific.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel.compat
import scala.annotation.{Annotation, StaticAnnotation}
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/compat/scalaVersionSpecific.scala b/kernel/src/main/scala-2.13+/cats/kernel/compat/scalaVersionSpecific.scala
index ed2415a255..d59fe29167 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/compat/scalaVersionSpecific.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/compat/scalaVersionSpecific.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/instances/AllInstances.scala b/kernel/src/main/scala-2.13+/cats/kernel/instances/AllInstances.scala
index 4fda9716a0..773ffaa80d 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/instances/AllInstances.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/instances/AllInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/instances/ArraySeqInstances.scala b/kernel/src/main/scala-2.13+/cats/kernel/instances/ArraySeqInstances.scala
index 2c7021b755..4a03c3a88e 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/instances/ArraySeqInstances.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/instances/ArraySeqInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/instances/LazyListInstances.scala b/kernel/src/main/scala-2.13+/cats/kernel/instances/LazyListInstances.scala
index 6b4a1bf71b..8f8a89103f 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/instances/LazyListInstances.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/instances/LazyListInstances.scala
@@ -1,11 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
+import scala.annotation.nowarn
+
trait LazyListInstances extends LazyListInstances1 {
implicit def catsKernelStdOrderForLazyList[A: Order]: Order[LazyList[A]] =
new LazyListOrder[A]
+
implicit def catsKernelStdMonoidForLazyList[A]: Monoid[LazyList[A]] =
- new LazyListMonoid[A]
+ LazyListMonoid[A]
}
private[instances] trait LazyListInstances1 extends LazyListInstances2 {
@@ -43,6 +67,7 @@ class LazyListEq[A](implicit ev: Eq[A]) extends Eq[LazyList[A]] {
else StaticMethods.iteratorEq(xs.iterator, ys.iterator)
}
+@deprecated("Use LazyListMonoid.apply, which does not allocate a new instance", "2.9.0")
class LazyListMonoid[A] extends Monoid[LazyList[A]] {
def empty: LazyList[A] = LazyList.empty
def combine(x: LazyList[A], y: LazyList[A]): LazyList[A] = x ++ y
@@ -52,3 +77,9 @@ class LazyListMonoid[A] extends Monoid[LazyList[A]] {
override def combineAll(xs: IterableOnce[LazyList[A]]): LazyList[A] =
StaticMethods.combineAllIterable(LazyList.newBuilder[A], xs)
}
+
+object LazyListMonoid {
+ @nowarn("msg=deprecated")
+ private[this] val singleton: Monoid[LazyList[Any]] = new LazyListMonoid[Any]
+ def apply[A]: Monoid[LazyList[A]] = singleton.asInstanceOf[Monoid[LazyList[A]]]
+}
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/instances/StreamInstances.scala b/kernel/src/main/scala-2.13+/cats/kernel/instances/StreamInstances.scala
index 3a748145c3..ec41033a7b 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/instances/StreamInstances.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/instances/StreamInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/instances/arraySeq/package.scala b/kernel/src/main/scala-2.13+/cats/kernel/instances/arraySeq/package.scala
index 2d829c75d6..eb81b88571 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/instances/arraySeq/package.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/instances/arraySeq/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala-2.13+/cats/kernel/instances/lazyList/package.scala b/kernel/src/main/scala-2.13+/cats/kernel/instances/lazyList/package.scala
index b1709ca425..2ea9604074 100644
--- a/kernel/src/main/scala-2.13+/cats/kernel/instances/lazyList/package.scala
+++ b/kernel/src/main/scala-2.13+/cats/kernel/instances/lazyList/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/Band.scala b/kernel/src/main/scala/cats/kernel/Band.scala
index 8e45b45053..9ab3d8d05a 100644
--- a/kernel/src/main/scala/cats/kernel/Band.scala
+++ b/kernel/src/main/scala/cats/kernel/Band.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.{specialized => sp}
@@ -21,8 +42,5 @@ object Band extends SemigroupFunctions[Band] {
/**
* Create a `Band` instance from the given function.
*/
- @inline def instance[A](cmb: (A, A) => A): Band[A] =
- new Band[A] {
- override def combine(x: A, y: A): A = cmb(x, y)
- }
+ @inline def instance[A](cmb: (A, A) => A): Band[A] = cmb(_, _)
}
diff --git a/kernel/src/main/scala/cats/kernel/Bounded.scala b/kernel/src/main/scala/cats/kernel/Bounded.scala
index 865d2b7b49..d485351204 100644
--- a/kernel/src/main/scala/cats/kernel/Bounded.scala
+++ b/kernel/src/main/scala/cats/kernel/Bounded.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import java.util.UUID
diff --git a/kernel/src/main/scala/cats/kernel/BoundedSemilattice.scala b/kernel/src/main/scala/cats/kernel/BoundedSemilattice.scala
index 9204c50967..d15100125e 100644
--- a/kernel/src/main/scala/cats/kernel/BoundedSemilattice.scala
+++ b/kernel/src/main/scala/cats/kernel/BoundedSemilattice.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.{specialized => sp}
@@ -23,7 +44,6 @@ object BoundedSemilattice extends SemilatticeFunctions[BoundedSemilattice] {
@inline def instance[A](emptyValue: A, cmb: (A, A) => A): BoundedSemilattice[A] =
new BoundedSemilattice[A] {
override val empty: A = emptyValue
-
override def combine(x: A, y: A): A = cmb(x, y)
}
}
diff --git a/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala b/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala
index 441ee2fcf1..ed5750d4fa 100644
--- a/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala
+++ b/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.{specialized => sp}
diff --git a/kernel/src/main/scala/cats/kernel/CommutativeMonoid.scala b/kernel/src/main/scala/cats/kernel/CommutativeMonoid.scala
index 03ac60421f..509d07b260 100644
--- a/kernel/src/main/scala/cats/kernel/CommutativeMonoid.scala
+++ b/kernel/src/main/scala/cats/kernel/CommutativeMonoid.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.{specialized => sp}
diff --git a/kernel/src/main/scala/cats/kernel/CommutativeSemigroup.scala b/kernel/src/main/scala/cats/kernel/CommutativeSemigroup.scala
index 137fce87c5..29e21a3f9b 100644
--- a/kernel/src/main/scala/cats/kernel/CommutativeSemigroup.scala
+++ b/kernel/src/main/scala/cats/kernel/CommutativeSemigroup.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.{specialized => sp}
@@ -33,8 +54,5 @@ object CommutativeSemigroup extends SemigroupFunctions[CommutativeSemigroup] {
/**
* Create a `CommutativeSemigroup` instance from the given function.
*/
- @inline def instance[A](cmb: (A, A) => A): CommutativeSemigroup[A] =
- new CommutativeSemigroup[A] {
- override def combine(x: A, y: A): A = cmb(x, y)
- }
+ @inline def instance[A](cmb: (A, A) => A): CommutativeSemigroup[A] = cmb(_, _)
}
diff --git a/kernel/src/main/scala/cats/kernel/Comparison.scala b/kernel/src/main/scala/cats/kernel/Comparison.scala
index 50d345792a..abe333fcfb 100644
--- a/kernel/src/main/scala/cats/kernel/Comparison.scala
+++ b/kernel/src/main/scala/cats/kernel/Comparison.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
/**
@@ -26,7 +47,7 @@ object Comparison {
else if (double == 0.0) SomeEq
else SomeLt
- implicit val catsKernelEqForComparison: Eq[Comparison] with Monoid[Comparison] =
+ implicit val catsKernelEqForComparison: Eq[Comparison] & Monoid[Comparison] =
new Eq[Comparison] with Monoid[Comparison] {
def eqv(x: Comparison, y: Comparison): Boolean = x == y
def empty: Comparison = EqualTo
diff --git a/kernel/src/main/scala/cats/kernel/Enumerable.scala b/kernel/src/main/scala/cats/kernel/Enumerable.scala
index 3c68cb004e..d287113d27 100644
--- a/kernel/src/main/scala/cats/kernel/Enumerable.scala
+++ b/kernel/src/main/scala/cats/kernel/Enumerable.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package kernel
diff --git a/kernel/src/main/scala/cats/kernel/Eq.scala b/kernel/src/main/scala/cats/kernel/Eq.scala
index 7de7eb694d..5f7dfe5a5c 100644
--- a/kernel/src/main/scala/cats/kernel/Eq.scala
+++ b/kernel/src/main/scala/cats/kernel/Eq.scala
@@ -1,12 +1,31 @@
-package cats.kernel
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
-import java.util.UUID
+package cats.kernel
import cats.kernel.compat.scalaVersionSpecific._
+import java.util.UUID
import scala.collection.immutable.{BitSet, Queue, Seq, SortedMap, SortedSet}
import scala.concurrent.duration.{Duration, FiniteDuration}
-import scala.math.Equiv
import scala.util.{Failure, Success, Try}
import scala.{specialized => sp}
@@ -44,9 +63,7 @@ trait EqToEquivConversion {
* instance.
*/
implicit def catsKernelEquivForEq[A](implicit ev: Eq[A]): Equiv[A] =
- new Equiv[A] {
- def equiv(a: A, b: A) = ev.eqv(a, b)
- }
+ ev.eqv(_, _)
}
@suppressUnusedImportWarningForScalaVersionSpecific
@@ -55,7 +72,7 @@ object Eq
with EqToEquivConversion
with ScalaVersionSpecificOrderInstances
with instances.TupleOrderInstances
- with OrderInstances0 {
+ with OrderInstances1 {
/**
* Access an implicit `Eq[A]`.
@@ -67,35 +84,26 @@ object Eq
* function `f`.
*/
def by[@sp A, @sp B](f: A => B)(implicit ev: Eq[B]): Eq[A] =
- new Eq[A] {
- def eqv(x: A, y: A) = ev.eqv(f(x), f(y))
- }
+ (x, y) => ev.eqv(f(x), f(y))
/**
* Return an Eq that gives the result of the and of eq1 and eq2
* note this is idempotent
*/
def and[@sp A](eq1: Eq[A], eq2: Eq[A]): Eq[A] =
- new Eq[A] {
- def eqv(x: A, y: A) = eq1.eqv(x, y) && eq2.eqv(x, y)
- }
+ (x, y) => eq1.eqv(x, y) && eq2.eqv(x, y)
/**
* Return an Eq that gives the result of the or of this and that
* Note this is idempotent
*/
def or[@sp A](eq1: Eq[A], eq2: Eq[A]): Eq[A] =
- new Eq[A] {
- def eqv(x: A, y: A) = eq1.eqv(x, y) || eq2.eqv(x, y)
- }
+ (x, y) => eq1.eqv(x, y) || eq2.eqv(x, y)
/**
* Create an `Eq` instance from an `eqv` implementation.
*/
- def instance[A](f: (A, A) => Boolean): Eq[A] =
- new Eq[A] {
- def eqv(x: A, y: A) = f(x, y)
- }
+ def instance[A](f: (A, A) => Boolean): Eq[A] = f(_, _)
/**
* An `Eq[A]` that delegates to universal equality (`==`).
@@ -103,18 +111,12 @@ object Eq
* This can be useful for case classes, which have reasonable `equals`
* implementations
*/
- def fromUniversalEquals[A]: Eq[A] =
- new Eq[A] {
- def eqv(x: A, y: A) = x == y
- }
+ def fromUniversalEquals[A]: Eq[A] = _ == _
/**
* Everything is the same
*/
- def allEqual[A]: Eq[A] =
- new Eq[A] {
- def eqv(x: A, y: A) = true
- }
+ def allEqual[A]: Eq[A] = (_, _) => true
/**
* This is a monoid that creates an Eq that
@@ -128,9 +130,7 @@ object Eq
if (es.iterator.isEmpty) None
else {
val materialized = es.iterator.toVector
- Some(new Eq[A] {
- def eqv(x: A, y: A) = materialized.forall(_.eqv(x, y))
- })
+ Some((x, y) => materialized.forall(_.eqv(x, y)))
}
}
@@ -145,49 +145,47 @@ object Eq
if (es.iterator.isEmpty) None
else {
val materialized = es.iterator.toVector
- Some(new Eq[A] {
- def eqv(x: A, y: A) = materialized.exists(_.eqv(x, y))
- })
+ Some((x, y) => materialized.exists(_.eqv(x, y)))
}
}
- implicit def catsKernelInstancesForBitSet: PartialOrder[BitSet] with Hash[BitSet] =
+ implicit def catsKernelInstancesForBitSet: PartialOrder[BitSet] & Hash[BitSet] =
cats.kernel.instances.bitSet.catsKernelStdOrderForBitSet
implicit def catsKernelPartialOrderForSet[A]: PartialOrder[Set[A]] =
cats.kernel.instances.set.catsKernelStdPartialOrderForSet[A]
implicit def catsKernelOrderForEither[A: Order, B: Order]: Order[Either[A, B]] =
cats.kernel.instances.either.catsStdOrderForEither[A, B]
- implicit def catsKernelInstancesForUnit: Order[Unit] with Hash[Unit] =
+ implicit def catsKernelInstancesForUnit: Order[Unit] & Hash[Unit] =
cats.kernel.instances.unit.catsKernelStdOrderForUnit
- implicit def catsKernelInstancesForBoolean: Order[Boolean] with Hash[Boolean] =
+ implicit def catsKernelInstancesForBoolean: Order[Boolean] & Hash[Boolean] =
cats.kernel.instances.boolean.catsKernelStdOrderForBoolean
- implicit def catsKernelInstancesForByte: Order[Byte] with Hash[Byte] =
+ implicit def catsKernelInstancesForByte: Order[Byte] & Hash[Byte] =
cats.kernel.instances.byte.catsKernelStdOrderForByte
- implicit def catsKernelInstancesForShort: Order[Short] with Hash[Short] =
+ implicit def catsKernelInstancesForShort: Order[Short] & Hash[Short] =
cats.kernel.instances.short.catsKernelStdOrderForShort
- implicit def catsKernelInstancesForInt: Order[Int] with Hash[Int] = cats.kernel.instances.int.catsKernelStdOrderForInt
- implicit def catsKernelInstancesForLong: Order[Long] with Hash[Long] =
+ implicit def catsKernelInstancesForInt: Order[Int] & Hash[Int] = cats.kernel.instances.int.catsKernelStdOrderForInt
+ implicit def catsKernelInstancesForLong: Order[Long] & Hash[Long] =
cats.kernel.instances.long.catsKernelStdOrderForLong
- implicit def catsKernelInstancesForBigInt: Order[BigInt] with Hash[BigInt] =
+ implicit def catsKernelInstancesForBigInt: Order[BigInt] & Hash[BigInt] =
cats.kernel.instances.bigInt.catsKernelStdOrderForBigInt
- implicit def catsKernelInstancesForBigDecimal: Order[BigDecimal] with Hash[BigDecimal] =
+ implicit def catsKernelInstancesForBigDecimal: Order[BigDecimal] & Hash[BigDecimal] =
cats.kernel.instances.bigDecimal.catsKernelStdOrderForBigDecimal
- implicit def catsKernelInstancesForDuration: Order[Duration] with Hash[Duration] =
+ implicit def catsKernelInstancesForDuration: Order[Duration] & Hash[Duration] =
cats.kernel.instances.duration.catsKernelStdOrderForDuration
- implicit def catsKernelInstancesForFiniteDuration: Order[FiniteDuration] with Hash[FiniteDuration] =
+ implicit def catsKernelInstancesForFiniteDuration: Order[FiniteDuration] & Hash[FiniteDuration] =
cats.kernel.instances.all.catsKernelStdOrderForFiniteDuration
- implicit def catsKernelInstancesForChar: Order[Char] with Hash[Char] =
+ implicit def catsKernelInstancesForChar: Order[Char] & Hash[Char] =
cats.kernel.instances.char.catsKernelStdOrderForChar
- implicit def catsKernelInstancesForSymbol: Order[Symbol] with Hash[Symbol] =
+ implicit def catsKernelInstancesForSymbol: Order[Symbol] & Hash[Symbol] =
cats.kernel.instances.symbol.catsKernelStdOrderForSymbol
- implicit def catsKernelInstancesForString: Order[String] with Hash[String] =
+ implicit def catsKernelInstancesForString: Order[String] & Hash[String] =
cats.kernel.instances.string.catsKernelStdOrderForString
- implicit def catsKernelInstancesForUUID: Order[UUID] with Hash[UUID] =
+ implicit def catsKernelInstancesForUUID: Order[UUID] & Hash[UUID] =
cats.kernel.instances.uuid.catsKernelStdOrderForUUID
- implicit def catsKernelInstancesForDouble: Order[Double] with Hash[Double] =
+ implicit def catsKernelInstancesForDouble: Order[Double] & Hash[Double] =
cats.kernel.instances.double.catsKernelStdOrderForDouble
- implicit def catsKernelInstancesForFloat: Order[Float] with Hash[Float] =
+ implicit def catsKernelInstancesForFloat: Order[Float] & Hash[Float] =
cats.kernel.instances.float.catsKernelStdOrderForFloat
implicit def catsKernelOrderForOption[A: Order]: Order[Option[A]] =
@@ -208,15 +206,11 @@ object Eq
* doing a fine grained equality on Throwable can make the code very execution
* order dependent
*/
- implicit def catsStdEqForTry[A, T](implicit A: Eq[A], T: Eq[Throwable]): Eq[Try[A]] =
- new Eq[Try[A]] {
- def eqv(x: Try[A], y: Try[A]): Boolean =
- (x, y) match {
- case (Success(a), Success(b)) => A.eqv(a, b)
- case (Failure(a), Failure(b)) => T.eqv(a, b)
- case _ => false
- }
- }
+ implicit def catsStdEqForTry[A](implicit A: Eq[A], T: Eq[Throwable]): Eq[Try[A]] = {
+ case (Success(a), Success(b)) => A.eqv(a, b)
+ case (Failure(a), Failure(b)) => T.eqv(a, b)
+ case _ => false
+ }
}
private[kernel] trait OrderInstances0 extends PartialOrderInstances {
@@ -224,7 +218,12 @@ private[kernel] trait OrderInstances0 extends PartialOrderInstances {
cats.kernel.instances.seq.catsKernelStdOrderForSeq[A]
}
-private[kernel] trait PartialOrderInstances extends PartialOrderInstances0 {
+private[kernel] trait OrderInstances1 extends OrderInstances0 {
+ implicit def catsKernelOrderForSortedMap[K, V: Order]: Order[SortedMap[K, V]] =
+ cats.kernel.instances.sortedMap.catsKernelStdOrderForSortedMap[K, V]
+}
+
+private[kernel] trait PartialOrderInstances extends PartialOrderInstances1 {
implicit def catsKernelPartialOrderForOption[A: PartialOrder]: PartialOrder[Option[A]] =
cats.kernel.instances.option.catsKernelStdPartialOrderForOption[A]
implicit def catsKernelPartialOrderForList[A: PartialOrder]: PartialOrder[List[A]] =
@@ -242,6 +241,11 @@ private[kernel] trait PartialOrderInstances0 extends HashInstances {
cats.kernel.instances.seq.catsKernelStdPartialOrderForSeq[A]
}
+private[kernel] trait PartialOrderInstances1 extends PartialOrderInstances0 {
+ implicit def catsKernelPartialOrderForSortedMap[K, V: PartialOrder]: PartialOrder[SortedMap[K, V]] =
+ cats.kernel.instances.sortedMap.catsKernelStdPartialOrderForSortedMap[K, V]
+}
+
private[kernel] trait HashInstances extends HashInstances0 {
implicit def catsKernelHashForSet[A]: Hash[Set[A]] = cats.kernel.instances.set.catsKernelStdHashForSet[A]
implicit def catsKernelHashForOption[A: Hash]: Hash[Option[A]] =
diff --git a/kernel/src/main/scala/cats/kernel/Group.scala b/kernel/src/main/scala/cats/kernel/Group.scala
index 785263bce7..0cc026e524 100644
--- a/kernel/src/main/scala/cats/kernel/Group.scala
+++ b/kernel/src/main/scala/cats/kernel/Group.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.{specialized => sp}
diff --git a/kernel/src/main/scala/cats/kernel/Hash.scala b/kernel/src/main/scala/cats/kernel/Hash.scala
index 87b2917e38..02bb7252ba 100644
--- a/kernel/src/main/scala/cats/kernel/Hash.scala
+++ b/kernel/src/main/scala/cats/kernel/Hash.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.{specialized => sp}
@@ -53,12 +74,9 @@ object Hash extends HashFunctions[Hash] {
def hash(x: A) = x.hashCode()
def eqv(x: A, y: A) = x == y
}
-
}
trait HashToHashingConversion {
implicit def catsKernelHashToHashing[A](implicit ev: Hash[A]): Hashing[A] =
- new Hashing[A] {
- override def hash(x: A): Int = ev.hash(x)
- }
+ ev.hash(_)
}
diff --git a/kernel/src/main/scala/cats/kernel/Monoid.scala b/kernel/src/main/scala/cats/kernel/Monoid.scala
index 3217610619..978fd98450 100644
--- a/kernel/src/main/scala/cats/kernel/Monoid.scala
+++ b/kernel/src/main/scala/cats/kernel/Monoid.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.{specialized => sp}
diff --git a/kernel/src/main/scala/cats/kernel/Order.scala b/kernel/src/main/scala/cats/kernel/Order.scala
index 4dff327518..ab0e80dc46 100644
--- a/kernel/src/main/scala/cats/kernel/Order.scala
+++ b/kernel/src/main/scala/cats/kernel/Order.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.{specialized => sp}
@@ -94,9 +115,7 @@ trait Order[@sp A] extends Any with PartialOrder[A] { self =>
* instance.
*/
def toOrdering: Ordering[A] =
- new Ordering[A] {
- def compare(x: A, y: A): Int = self.compare(x, y)
- }
+ compare(_, _)
}
abstract class OrderFunctions[O[T] <: Order[T]] extends PartialOrderFunctions[O] {
@@ -137,17 +156,13 @@ object Order extends OrderFunctions[Order] with OrderToOrderingConversion {
* function `f`.
*/
def by[@sp A, @sp B](f: A => B)(implicit ev: Order[B]): Order[A] =
- new Order[A] {
- def compare(x: A, y: A): Int = ev.compare(f(x), f(y))
- }
+ (x, y) => ev.compare(f(x), f(y))
/**
* Defines an ordering on `A` from the given order such that all arrows switch direction.
*/
def reverse[@sp A](order: Order[A]): Order[A] =
- new Order[A] {
- def compare(x: A, y: A): Int = order.compare(y, x)
- }
+ (x, y) => order.compare(y, x)
/**
* Returns a new `Order[A]` instance that first compares by the first
@@ -156,22 +171,16 @@ object Order extends OrderFunctions[Order] with OrderToOrderingConversion {
* That is, `Order.whenEqual(x, y)` creates an `Order` that first orders by `x` and
* then (if two elements are equal) falls back to `y` for the comparison.
*/
- def whenEqual[@sp A](first: Order[A], second: Order[A]): Order[A] =
- new Order[A] {
- def compare(x: A, y: A) = {
- val c = first.compare(x, y)
- if (c == 0) second.compare(x, y)
- else c
- }
- }
+ def whenEqual[@sp A](first: Order[A], second: Order[A]): Order[A] = { (x, y) =>
+ val c = first.compare(x, y)
+ if (c == 0) second.compare(x, y)
+ else c
+ }
/**
* Define an `Order[A]` using the given function `f`.
*/
- def from[@sp A](f: (A, A) => Int): Order[A] =
- new Order[A] {
- def compare(x: A, y: A) = f(x, y)
- }
+ def from[@sp A](f: (A, A) => Int): Order[A] = f(_, _)
/**
* Define an `Order[A]` using the given 'less than' function `f`.
@@ -194,9 +203,7 @@ object Order extends OrderFunctions[Order] with OrderToOrderingConversion {
* An `Order` instance that considers all `A` instances to be equal.
*/
def allEqual[A]: Order[A] =
- new Order[A] {
- def compare(x: A, y: A): Int = 0
- }
+ (_, _) => 0
/**
* A `Monoid[Order[A]]` can be generated for all `A` with the following
@@ -213,7 +220,7 @@ object Order extends OrderFunctions[Order] with OrderToOrderingConversion {
*
* @see [[Order.whenEqual]]
*/
- def whenEqualMonoid[A]: Monoid[Order[A]] with Band[Order[A]] =
+ def whenEqualMonoid[A]: Monoid[Order[A]] & Band[Order[A]] =
new Monoid[Order[A]] with Band[Order[A]] {
val empty: Order[A] = allEqual[A]
def combine(x: Order[A], y: Order[A]): Order[A] = Order.whenEqual(x, y)
@@ -222,13 +229,8 @@ object Order extends OrderFunctions[Order] with OrderToOrderingConversion {
def fromOrdering[A](implicit ev: Ordering[A]): Order[A] =
new Order[A] {
def compare(x: A, y: A): Int = ev.compare(x, y)
-
override def toOrdering: Ordering[A] = ev
}
- def fromComparable[A <: Comparable[A]]: Order[A] =
- new Order[A] {
- override def compare(x: A, y: A): Int =
- x.compareTo(y)
- }
+ def fromComparable[A <: Comparable[A]]: Order[A] = _ compareTo _
}
diff --git a/kernel/src/main/scala/cats/kernel/PartialOrder.scala b/kernel/src/main/scala/cats/kernel/PartialOrder.scala
index 383b068292..2547883b76 100644
--- a/kernel/src/main/scala/cats/kernel/PartialOrder.scala
+++ b/kernel/src/main/scala/cats/kernel/PartialOrder.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import java.lang.Double.isNaN
@@ -141,31 +162,21 @@ object PartialOrder extends PartialOrderFunctions[PartialOrder] with PartialOrde
* function `f`.
*/
def by[@sp A, @sp B](f: A => B)(implicit ev: PartialOrder[B]): PartialOrder[A] =
- new PartialOrder[A] {
- def partialCompare(x: A, y: A): Double = ev.partialCompare(f(x), f(y))
- }
+ (x, y) => ev.partialCompare(f(x), f(y))
/**
* Defines a partial order on `A` from p where all arrows switch direction.
*/
def reverse[@sp A](p: PartialOrder[A]): PartialOrder[A] =
- new PartialOrder[A] {
- def partialCompare(x: A, y: A): Double = p.partialCompare(y, x)
- }
+ (x, y) => p.partialCompare(y, x)
/**
* Define a `PartialOrder[A]` using the given function `f`.
*/
- def from[@sp A](f: (A, A) => Double): PartialOrder[A] =
- new PartialOrder[A] {
- def partialCompare(x: A, y: A) = f(x, y)
- }
+ def from[@sp A](f: (A, A) => Double): PartialOrder[A] = f(_, _)
def fromPartialOrdering[A](implicit ev: PartialOrdering[A]): PartialOrder[A] =
- new PartialOrder[A] {
- def partialCompare(x: A, y: A): Double =
- ev.tryCompare(x, y).fold(Double.NaN)(_.toDouble)
- }
+ ev.tryCompare(_, _).fold(Double.NaN)(_.toDouble)
}
trait PartialOrderToPartialOrderingConversion {
diff --git a/kernel/src/main/scala/cats/kernel/Semigroup.scala b/kernel/src/main/scala/cats/kernel/Semigroup.scala
index 7ae7cc5cf4..9150d02dee 100644
--- a/kernel/src/main/scala/cats/kernel/Semigroup.scala
+++ b/kernel/src/main/scala/cats/kernel/Semigroup.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.annotation.tailrec
@@ -99,10 +120,7 @@ trait Semigroup[@sp(Int, Long, Float, Double) A] extends Any with Serializable {
* This name matches the term used in Foldable and Reducible and a similar Haskell function.
*/
def intercalate(middle: A): Semigroup[A] =
- new Semigroup[A] {
- def combine(a: A, b: A): A =
- self.combine(a, self.combine(middle, b))
- }
+ (a, b) => self.combine(a, self.combine(middle, b))
}
abstract class SemigroupFunctions[S[T] <: Semigroup[T]] {
@@ -122,10 +140,10 @@ abstract class SemigroupFunctions[S[T] <: Semigroup[T]] {
}
def isCommutative[A](implicit ev: S[A]): Boolean =
- ev.isInstanceOf[CommutativeSemigroup[_]]
+ ev.isInstanceOf[CommutativeSemigroup[?]]
def isIdempotent[A](implicit ev: S[A]): Boolean =
- ev.isInstanceOf[Band[_]]
+ ev.isInstanceOf[Band[?]]
def combineN[@sp(Int, Long, Float, Double) A](a: A, n: Int)(implicit ev: S[A]): A =
ev.combineN(a, n)
@@ -148,30 +166,24 @@ object Semigroup
/**
* Create a `Semigroup` instance from the given function.
*/
- @inline def instance[A](cmb: (A, A) => A): Semigroup[A] =
- new Semigroup[A] {
- override def combine(x: A, y: A): A = cmb(x, y)
- }
+ @inline def instance[A](cmb: (A, A) => A): Semigroup[A] = cmb(_, _)
/**
* Create a `Semigroup` instance that always returns the lefthand side.
*/
- @inline def first[A]: Semigroup[A] =
- new Semigroup[A] {
- override def combine(x: A, y: A): A = x
- }
+ @inline def first[A]: Semigroup[A] = (x, _) => x
/**
* Create a `Semigroup` instance that always returns the righthand side.
*/
- @inline def last[A]: Semigroup[A] =
- new Semigroup[A] {
- override def combine(x: A, y: A): A = y
- }
+ @inline def last[A]: Semigroup[A] = (_, y) => y
+
+ @inline def intercalate[A](sep: A)(implicit ev: Semigroup[A]): Semigroup[A] =
+ ev.intercalate(sep)
implicit def catsKernelBoundedSemilatticeForBitSet: BoundedSemilattice[BitSet] =
cats.kernel.instances.bitSet.catsKernelStdSemilatticeForBitSet
- implicit def catsKernelInstancesForUnit: BoundedSemilattice[Unit] with CommutativeGroup[Unit] =
+ implicit def catsKernelInstancesForUnit: BoundedSemilattice[Unit] & CommutativeGroup[Unit] =
cats.kernel.instances.unit.catsKernelStdAlgebraForUnit
implicit def catsKernelCommutativeGroupForByte: CommutativeGroup[Byte] =
cats.kernel.instances.byte.catsKernelStdGroupForByte
@@ -267,8 +279,19 @@ private[kernel] trait MonoidInstances extends BandInstances {
cats.kernel.instances.either.catsDataMonoidForEither[A, B]
implicit def catsKernelMonoidForTry[A: Monoid]: Monoid[Try[A]] =
new TryMonoid[A](Monoid[A])
+
+ /**
+ * @deprecated
+ * Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
+ * (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
+ * We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
+ * However, at this time there are no plans to remove these instances from Cats.
+ *
+ * @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
+ */
implicit def catsKernelMonoidForFuture[A](implicit A: Monoid[A], ec: ExecutionContext): Monoid[Future[A]] =
new FutureMonoid[A](A, ec)
+
implicit def catsKernelMonoidForOption[A: Semigroup]: Monoid[Option[A]] =
cats.kernel.instances.option.catsKernelStdMonoidForOption[A]
implicit def catsKernelMonoidForSeq[A]: Monoid[Seq[A]] =
@@ -298,6 +321,15 @@ private[kernel] trait SemigroupInstances {
cats.kernel.instances.either.catsDataSemigroupForEither[A, B]
implicit def catsKernelSemigroupForTry[A: Semigroup]: Semigroup[Try[A]] =
new TrySemigroup[A](Semigroup[A])
+
+ /**
+ * @deprecated
+ * Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
+ * (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
+ * We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
+ *
+ * @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
+ */
implicit def catsKernelSemigroupForFuture[A](implicit A: Semigroup[A], ec: ExecutionContext): Semigroup[Future[A]] =
new FutureSemigroup[A](A, ec)
}
diff --git a/kernel/src/main/scala/cats/kernel/Semilattice.scala b/kernel/src/main/scala/cats/kernel/Semilattice.scala
index 631de852f5..f3357e969a 100644
--- a/kernel/src/main/scala/cats/kernel/Semilattice.scala
+++ b/kernel/src/main/scala/cats/kernel/Semilattice.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
import scala.{specialized => sp}
@@ -20,14 +41,11 @@ trait Semilattice[@sp(Int, Long, Float, Double) A] extends Any with Band[A] with
* 1.0 if y = combine(x, y)
* NaN otherwise
*/
- def asMeetPartialOrder(implicit ev: Eq[A]): PartialOrder[A] =
- new PartialOrder[A] {
- def partialCompare(x: A, y: A): Double =
- if (ev.eqv(x, y)) 0.0
- else {
- val z = self.combine(x, y)
- if (ev.eqv(x, z)) -1.0 else if (ev.eqv(y, z)) 1.0 else Double.NaN
- }
+ def asMeetPartialOrder(implicit ev: Eq[A]): PartialOrder[A] = (x, y) =>
+ if (ev.eqv(x, y)) 0.0
+ else {
+ val z = self.combine(x, y)
+ if (ev.eqv(x, z)) -1.0 else if (ev.eqv(y, z)) 1.0 else Double.NaN
}
/**
@@ -42,14 +60,11 @@ trait Semilattice[@sp(Int, Long, Float, Double) A] extends Any with Band[A] with
* 1.0 if x = combine(x, y)
* NaN otherwise
*/
- def asJoinPartialOrder(implicit ev: Eq[A]): PartialOrder[A] =
- new PartialOrder[A] {
- def partialCompare(x: A, y: A): Double =
- if (ev.eqv(x, y)) 0.0
- else {
- val z = self.combine(x, y)
- if (ev.eqv(y, z)) -1.0 else if (ev.eqv(x, z)) 1.0 else Double.NaN
- }
+ def asJoinPartialOrder(implicit ev: Eq[A]): PartialOrder[A] = (x, y) =>
+ if (ev.eqv(x, y)) 0.0
+ else {
+ val z = self.combine(x, y)
+ if (ev.eqv(y, z)) -1.0 else if (ev.eqv(x, z)) 1.0 else Double.NaN
}
}
@@ -70,8 +85,5 @@ object Semilattice extends SemilatticeFunctions[Semilattice] {
/**
* Create a `Semilattice` instance from the given function.
*/
- @inline def instance[A](cmb: (A, A) => A): Semilattice[A] =
- new Semilattice[A] {
- override def combine(x: A, y: A): A = cmb(x, y)
- }
+ @inline def instance[A](cmb: (A, A) => A): Semilattice[A] = cmb(_, _)
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/BigDecimalInstances.scala b/kernel/src/main/scala/cats/kernel/instances/BigDecimalInstances.scala
index 439c59ad92..2e430423b1 100644
--- a/kernel/src/main/scala/cats/kernel/instances/BigDecimalInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/BigDecimalInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait BigDecimalInstances {
- implicit val catsKernelStdOrderForBigDecimal: Order[BigDecimal] with Hash[BigDecimal] =
+ implicit val catsKernelStdOrderForBigDecimal: Order[BigDecimal] & Hash[BigDecimal] =
new BigDecimalOrder
implicit val catsKernelStdGroupForBigDecimal: CommutativeGroup[BigDecimal] =
new BigDecimalGroup
diff --git a/kernel/src/main/scala/cats/kernel/instances/BigIntInstances.scala b/kernel/src/main/scala/cats/kernel/instances/BigIntInstances.scala
index 4741f74179..c0d55700b5 100644
--- a/kernel/src/main/scala/cats/kernel/instances/BigIntInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/BigIntInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait BigIntInstances {
- implicit val catsKernelStdOrderForBigInt: Order[BigInt] with Hash[BigInt] with UnboundedEnumerable[BigInt] =
+ implicit val catsKernelStdOrderForBigInt: Order[BigInt] & Hash[BigInt] & UnboundedEnumerable[BigInt] =
new BigIntOrder
implicit val catsKernelStdGroupForBigInt: CommutativeGroup[BigInt] =
new BigIntGroup
diff --git a/kernel/src/main/scala/cats/kernel/instances/BitSetInstances.scala b/kernel/src/main/scala/cats/kernel/instances/BitSetInstances.scala
index 5787ba8001..5ac0ea8a04 100644
--- a/kernel/src/main/scala/cats/kernel/instances/BitSetInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/BitSetInstances.scala
@@ -1,10 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
import scala.collection.immutable.BitSet
trait BitSetInstances {
- implicit val catsKernelStdOrderForBitSet: PartialOrder[BitSet] with Hash[BitSet] =
+ implicit val catsKernelStdOrderForBitSet: PartialOrder[BitSet] & Hash[BitSet] =
new BitSetPartialOrder
implicit val catsKernelStdSemilatticeForBitSet: BoundedSemilattice[BitSet] =
diff --git a/kernel/src/main/scala/cats/kernel/instances/BooleanInstances.scala b/kernel/src/main/scala/cats/kernel/instances/BooleanInstances.scala
index 69656e34a9..073567990d 100644
--- a/kernel/src/main/scala/cats/kernel/instances/BooleanInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/BooleanInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait BooleanInstances {
- implicit val catsKernelStdOrderForBoolean: Order[Boolean] with Hash[Boolean] with BoundedEnumerable[Boolean] =
+ implicit val catsKernelStdOrderForBoolean: Order[Boolean] & Hash[Boolean] & BoundedEnumerable[Boolean] =
new BooleanOrder
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/ByteInstances.scala b/kernel/src/main/scala/cats/kernel/instances/ByteInstances.scala
index 7ba66a1e76..1d1a146ede 100644
--- a/kernel/src/main/scala/cats/kernel/instances/ByteInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/ByteInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait ByteInstances {
- implicit val catsKernelStdOrderForByte: Order[Byte] with Hash[Byte] with BoundedEnumerable[Byte] =
+ implicit val catsKernelStdOrderForByte: Order[Byte] & Hash[Byte] & BoundedEnumerable[Byte] =
new ByteOrder
implicit val catsKernelStdGroupForByte: CommutativeGroup[Byte] = new ByteGroup
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/CharInstances.scala b/kernel/src/main/scala/cats/kernel/instances/CharInstances.scala
index 14a0e6061b..a6ce953410 100644
--- a/kernel/src/main/scala/cats/kernel/instances/CharInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/CharInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait CharInstances {
- implicit val catsKernelStdOrderForChar: CharOrder with Hash[Char] with BoundedEnumerable[Char] = new CharOrder
+ implicit val catsKernelStdOrderForChar: CharOrder & Hash[Char] & BoundedEnumerable[Char] = new CharOrder
}
trait CharEnumerable extends BoundedEnumerable[Char] {
diff --git a/kernel/src/main/scala/cats/kernel/instances/DeadlineInstances.scala b/kernel/src/main/scala/cats/kernel/instances/DeadlineInstances.scala
index 330e4b46ba..f36e66462c 100644
--- a/kernel/src/main/scala/cats/kernel/instances/DeadlineInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/DeadlineInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
@@ -6,7 +27,7 @@ import scala.concurrent.duration.{Deadline, FiniteDuration}
trait DeadlineInstances {
implicit val catsKernelStdOrderForDeadline
- : Order[Deadline] with Hash[Deadline] with LowerBounded[Deadline] with UpperBounded[Deadline] = new DeadlineOrder
+ : Order[Deadline] & Hash[Deadline] & LowerBounded[Deadline] & UpperBounded[Deadline] = new DeadlineOrder
}
trait DeadlineBounded extends LowerBounded[Deadline] with UpperBounded[Deadline] {
diff --git a/kernel/src/main/scala/cats/kernel/instances/DoubleInstances.scala b/kernel/src/main/scala/cats/kernel/instances/DoubleInstances.scala
index a993dbe6b9..240a69b54e 100644
--- a/kernel/src/main/scala/cats/kernel/instances/DoubleInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/DoubleInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait DoubleInstances {
- implicit val catsKernelStdOrderForDouble: Order[Double] with Hash[Double] = new DoubleOrder
+ implicit val catsKernelStdOrderForDouble: Order[Double] & Hash[Double] = new DoubleOrder
implicit val catsKernelStdGroupForDouble: CommutativeGroup[Double] = new DoubleGroup
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/DurationInstances.scala b/kernel/src/main/scala/cats/kernel/instances/DurationInstances.scala
index 58f8816360..22314757d7 100644
--- a/kernel/src/main/scala/cats/kernel/instances/DurationInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/DurationInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
@@ -5,7 +26,7 @@ import scala.concurrent.duration.Duration
trait DurationInstances {
implicit val catsKernelStdOrderForDuration
- : Order[Duration] with Hash[Duration] with LowerBounded[Duration] with UpperBounded[Duration] = new DurationOrder
+ : Order[Duration] & Hash[Duration] & LowerBounded[Duration] & UpperBounded[Duration] = new DurationOrder
implicit val catsKernelStdGroupForDuration: CommutativeGroup[Duration] = new DurationGroup
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/EitherInstances.scala b/kernel/src/main/scala/cats/kernel/instances/EitherInstances.scala
index b57079e2ed..4d156a3220 100644
--- a/kernel/src/main/scala/cats/kernel/instances/EitherInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/EitherInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
@@ -39,17 +60,15 @@ trait EitherInstances extends EitherInstances0 {
private[instances] trait EitherInstances0 extends EitherInstances1 {
implicit def catsDataSemigroupForEither[A, B](implicit B: Semigroup[B]): Semigroup[Either[A, B]] =
- new Semigroup[Either[A, B]] {
- def combine(x: Either[A, B], y: Either[A, B]): Either[A, B] =
- x match {
- case left @ Left(_) => left
- case Right(xx) =>
- y match {
- case left @ Left(_) => left
- case Right(yy) => Right(B.combine(xx, yy))
- }
- }
- }
+ (x, y) =>
+ x match {
+ case left @ Left(_) => left
+ case Right(xx) =>
+ y match {
+ case left @ Left(_) => left
+ case Right(yy) => Right(B.combine(xx, yy))
+ }
+ }
implicit def catsStdPartialOrderForEither[A, B](implicit
A: PartialOrder[A],
diff --git a/kernel/src/main/scala/cats/kernel/instances/FiniteDurationInstances.scala b/kernel/src/main/scala/cats/kernel/instances/FiniteDurationInstances.scala
index b616311f8d..91ac2757a1 100644
--- a/kernel/src/main/scala/cats/kernel/instances/FiniteDurationInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/FiniteDurationInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
@@ -6,10 +27,9 @@ import java.util.concurrent.TimeUnit
import scala.concurrent.duration.{Duration, FiniteDuration}
trait FiniteDurationInstances {
- implicit val catsKernelStdOrderForFiniteDuration: Order[FiniteDuration]
- with Hash[FiniteDuration]
- with LowerBounded[FiniteDuration]
- with UpperBounded[FiniteDuration] = new FiniteDurationOrder
+ implicit val catsKernelStdOrderForFiniteDuration
+ : Order[FiniteDuration] & Hash[FiniteDuration] & LowerBounded[FiniteDuration] & UpperBounded[FiniteDuration] =
+ new FiniteDurationOrder
implicit val catsKernelStdGroupForFiniteDuration: CommutativeGroup[FiniteDuration] = new FiniteDurationGroup
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/FloatInstances.scala b/kernel/src/main/scala/cats/kernel/instances/FloatInstances.scala
index cdac895e19..42b0838694 100644
--- a/kernel/src/main/scala/cats/kernel/instances/FloatInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/FloatInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait FloatInstances {
- implicit val catsKernelStdOrderForFloat: Order[Float] with Hash[Float] = new FloatOrder
+ implicit val catsKernelStdOrderForFloat: Order[Float] & Hash[Float] = new FloatOrder
implicit val catsKernelStdGroupForFloat: CommutativeGroup[Float] = new FloatGroup
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/FunctionInstances.scala b/kernel/src/main/scala/cats/kernel/instances/FunctionInstances.scala
index 87f2bd7c04..6451507692 100644
--- a/kernel/src/main/scala/cats/kernel/instances/FunctionInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/FunctionInstances.scala
@@ -1,12 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
+import cats.kernel.compat.scalaVersionSpecific._
+import scala.util.control.TailCalls.{done, tailcall, TailRec}
+
+@suppressUnusedImportWarningForScalaVersionSpecific
trait FunctionInstances extends FunctionInstances0 {
implicit def catsKernelOrderForFunction0[A](implicit ev: Order[A]): Order[() => A] =
- new Order[() => A] {
- def compare(x: () => A, y: () => A): Int = ev.compare(x(), y())
- }
+ Order.by(_.apply())
implicit def catsKernelCommutativeGroupForFunction0[A](implicit G: CommutativeGroup[A]): CommutativeGroup[() => A] =
new Function0Group[A] with CommutativeGroup[() => A] { def A: Group[A] = G }
@@ -24,9 +47,7 @@ private[instances] trait FunctionInstances0 extends FunctionInstances1 {
}
implicit def catsKernelPartialOrderForFunction0[A](implicit ev: PartialOrder[A]): PartialOrder[() => A] =
- new PartialOrder[() => A] {
- def partialCompare(x: () => A, y: () => A): Double = ev.partialCompare(x(), y())
- }
+ PartialOrder.by(_.apply())
implicit def catsKernelGroupForFunction0[A](implicit G: Group[A]): Group[() => A] =
new Function0Group[A] { def A: Group[A] = G }
@@ -48,9 +69,7 @@ private[instances] trait FunctionInstances0 extends FunctionInstances1 {
private[instances] trait FunctionInstances1 extends FunctionInstances2 {
implicit def catsKernelEqForFunction0[A](implicit ev: Eq[A]): Eq[() => A] =
- new Eq[() => A] {
- def eqv(x: () => A, y: () => A): Boolean = ev.eqv(x(), y())
- }
+ Eq.by(_.apply())
implicit def catsKernelCommutativeMonoidForFunction0[A](implicit
M: CommutativeMonoid[A]
@@ -106,11 +125,33 @@ private[instances] trait FunctionInstances4 {
new Function1Semigroup[A, B] { def B: Semigroup[B] = S }
}
+final private[instances] case class CombineFunction1[A, B](left: A => B, right: A => B, semiB: Semigroup[B])
+ extends (A => B) {
+ private def call(fn: A => B, a: A): TailRec[B] =
+ fn match {
+ case ref: CombineFunction1[A, B] @unchecked =>
+ for {
+ lb <- tailcall(call(ref.left, a))
+ rb <- tailcall(call(ref.right, a))
+ } yield ref.semiB.combine(lb, rb)
+ case _ => done(fn(a))
+ }
+
+ final override def apply(a: A): B = call(this, a).result
+}
+
trait Function1Semigroup[A, B] extends Semigroup[A => B] {
implicit def B: Semigroup[B]
override def combine(x: A => B, y: A => B): A => B =
- (a: A) => B.combine(x(a), y(a))
+ CombineFunction1(x, y, B)
+
+ override def combineAllOption(fns: IterableOnce[A => B]): Option[A => B] =
+ if (fns.iterator.isEmpty) None
+ else
+ Some { (a: A) =>
+ B.combineAllOption(fns.iterator.map(_.apply(a))).get
+ }
}
trait Function1Monoid[A, B] extends Function1Semigroup[A, B] with Monoid[A => B] {
@@ -127,11 +168,33 @@ trait Function1Group[A, B] extends Function1Monoid[A, B] with Group[A => B] {
(a: A) => B.inverse(x(a))
}
+final private[instances] case class CombineFunction0[A](left: () => A, right: () => A, semiA: Semigroup[A])
+ extends (() => A) {
+ private def call(fn: () => A): TailRec[A] =
+ fn match {
+ case ref: CombineFunction0[A] @unchecked =>
+ for {
+ la <- tailcall(call(ref.left))
+ ra <- tailcall(call(ref.right))
+ } yield ref.semiA.combine(la, ra)
+ case _ => done(fn())
+ }
+
+ final override def apply(): A = call(this).result
+}
+
trait Function0Semigroup[A] extends Semigroup[() => A] {
implicit def A: Semigroup[A]
override def combine(x: () => A, y: () => A): () => A =
- () => A.combine(x(), y())
+ CombineFunction0(x, y, A)
+
+ override def combineAllOption(fns: IterableOnce[() => A]): Option[() => A] =
+ if (fns.iterator.isEmpty) None
+ else
+ Some { () =>
+ A.combineAllOption(fns.iterator.map(_.apply())).get
+ }
}
trait Function0Monoid[A] extends Function0Semigroup[A] with Monoid[() => A] {
diff --git a/kernel/src/main/scala/cats/kernel/instances/IntInstances.scala b/kernel/src/main/scala/cats/kernel/instances/IntInstances.scala
index 9d268e6deb..9980bca8bb 100644
--- a/kernel/src/main/scala/cats/kernel/instances/IntInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/IntInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait IntInstances {
- implicit val catsKernelStdOrderForInt: Order[Int] with Hash[Int] with BoundedEnumerable[Int] =
+ implicit val catsKernelStdOrderForInt: Order[Int] & Hash[Int] & BoundedEnumerable[Int] =
new IntOrder
implicit val catsKernelStdGroupForInt: CommutativeGroup[Int] = new IntGroup
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/ListInstances.scala b/kernel/src/main/scala/cats/kernel/instances/ListInstances.scala
index a23e846469..59720af4e2 100644
--- a/kernel/src/main/scala/cats/kernel/instances/ListInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/ListInstances.scala
@@ -1,15 +1,37 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
-import scala.annotation.tailrec
+import scala.annotation.{nowarn, tailrec}
import compat.scalaVersionSpecific._
@suppressUnusedImportWarningForScalaVersionSpecific
trait ListInstances extends ListInstances1 {
implicit def catsKernelStdOrderForList[A: Order]: Order[List[A]] =
new ListOrder[A]
+
implicit def catsKernelStdMonoidForList[A]: Monoid[List[A]] =
- new ListMonoid[A]
+ ListMonoid[A]
}
private[instances] trait ListInstances1 extends ListInstances2 {
@@ -83,6 +105,7 @@ class ListEq[A](implicit ev: Eq[A]) extends Eq[List[A]] {
}
}
+@deprecated("Use ListMonoid.apply, which does not allocate a new instance", "2.9.0")
class ListMonoid[A] extends Monoid[List[A]] { self =>
def empty: List[A] = Nil
def combine(x: List[A], y: List[A]): List[A] = x ::: y
@@ -103,6 +126,12 @@ class ListMonoid[A] extends Monoid[List[A]] { self =>
item ::: acc
}
- override def reverse = self
+ override def reverse: Monoid[List[A]] = self
}
}
+
+object ListMonoid {
+ @nowarn("msg=deprecated")
+ private[this] val singleton: Monoid[List[Any]] = new ListMonoid[Any]
+ def apply[A]: Monoid[List[A]] = singleton.asInstanceOf[Monoid[List[A]]]
+}
diff --git a/kernel/src/main/scala/cats/kernel/instances/LongInstances.scala b/kernel/src/main/scala/cats/kernel/instances/LongInstances.scala
index 5df92ec563..76882f3ed2 100644
--- a/kernel/src/main/scala/cats/kernel/instances/LongInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/LongInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait LongInstances {
- implicit val catsKernelStdOrderForLong: Order[Long] with Hash[Long] with BoundedEnumerable[Long] =
+ implicit val catsKernelStdOrderForLong: Order[Long] & Hash[Long] & BoundedEnumerable[Long] =
new LongOrder
implicit val catsKernelStdGroupForLong: CommutativeGroup[Long] = new LongGroup
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/MapInstances.scala b/kernel/src/main/scala/cats/kernel/instances/MapInstances.scala
index 9ba156ad80..528063e7cf 100644
--- a/kernel/src/main/scala/cats/kernel/instances/MapInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/MapInstances.scala
@@ -1,12 +1,56 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* This file is derived in part from https://github.com/scala/scala/blob/v2.12.2/src/library/scala/util/hashing/MurmurHash3.scala
+ * Modified by Typelevel for redistribution in Cats.
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ * Scala
+ * Copyright (c) 2002-2022 EPFL
+ * Copyright (c) 2011-2022 Lightbend, Inc.
+ *
+ * Scala includes software developed at
+ * LAMP/EPFL (https://lamp.epfl.ch/) and
+ * Lightbend, Inc. (https://www.lightbend.com/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package cats.kernel
package instances
+import org.typelevel.scalaccompat.annotation.unused
+
import scala.collection.mutable
+
import compat.scalaVersionSpecific._
@suppressUnusedImportWarningForScalaVersionSpecific
trait MapInstances extends MapInstances1 {
- implicit def catsKernelStdHashForMap[K: Hash, V: Hash]: Hash[Map[K, V]] =
+ implicit def catsKernelStdHashForMap[K, V](implicit @unused K: Hash[K], V: Hash[V]): Hash[Map[K, V]] =
new MapHash[K, V]
implicit def catsKernelStdCommutativeMonoidForMap[K, V: CommutativeSemigroup]: CommutativeMonoid[Map[K, V]] =
diff --git a/kernel/src/main/scala/cats/kernel/instances/OptionInstances.scala b/kernel/src/main/scala/cats/kernel/instances/OptionInstances.scala
index 121bf49862..ddf7510706 100644
--- a/kernel/src/main/scala/cats/kernel/instances/OptionInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/OptionInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/QueueInstances.scala b/kernel/src/main/scala/cats/kernel/instances/QueueInstances.scala
index 76a8ec7e18..a266f61345 100644
--- a/kernel/src/main/scala/cats/kernel/instances/QueueInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/QueueInstances.scala
@@ -1,15 +1,37 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
import scala.collection.immutable.Queue
import compat.scalaVersionSpecific._
+import scala.annotation.nowarn
+
@suppressUnusedImportWarningForScalaVersionSpecific
trait QueueInstances extends QueueInstances1 {
implicit def catsKernelStdOrderForQueue[A: Order]: Order[Queue[A]] =
new QueueOrder[A]
- implicit def catsKernelStdMonoidForQueue[A]: Monoid[Queue[A]] =
- new QueueMonoid[A]
+ implicit def catsKernelStdMonoidForQueue[A]: Monoid[Queue[A]] = QueueMonoid[A]
}
private[instances] trait QueueInstances1 extends QueueInstances2 {
@@ -47,6 +69,7 @@ class QueueEq[A](implicit ev: Eq[A]) extends Eq[Queue[A]] {
else StaticMethods.iteratorEq(xs.iterator, ys.iterator)
}
+@deprecated("Use QueueMonoid.apply, which does not allocate a new instance", "2.9.0")
class QueueMonoid[A] extends Monoid[Queue[A]] {
def empty: Queue[A] = Queue.empty[A]
def combine(x: Queue[A], y: Queue[A]): Queue[A] = x ++ y
@@ -57,3 +80,10 @@ class QueueMonoid[A] extends Monoid[Queue[A]] {
override def combineAll(xs: IterableOnce[Queue[A]]): Queue[A] =
StaticMethods.combineAllIterable(Queue.newBuilder[A], xs)
}
+
+object QueueMonoid {
+ @nowarn("msg=deprecated")
+ private[this] val singleton: Monoid[Queue[Any]] = new QueueMonoid[Any]
+
+ def apply[A]: Monoid[Queue[A]] = singleton.asInstanceOf[Monoid[Queue[A]]]
+}
diff --git a/kernel/src/main/scala/cats/kernel/instances/SeqInstances.scala b/kernel/src/main/scala/cats/kernel/instances/SeqInstances.scala
index e2e51e9cb0..6282c5e894 100644
--- a/kernel/src/main/scala/cats/kernel/instances/SeqInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/SeqInstances.scala
@@ -1,15 +1,38 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
-import compat.scalaVersionSpecific._
+import scala.annotation.nowarn
import scala.collection.immutable.Seq
+import compat.scalaVersionSpecific._
+
@suppressUnusedImportWarningForScalaVersionSpecific
trait SeqInstances extends SeqInstances1 {
implicit def catsKernelStdOrderForSeq[A: Order]: Order[Seq[A]] =
new SeqOrder[A]
implicit def catsKernelStdMonoidForSeq[A]: Monoid[Seq[A]] =
- new SeqMonoid[A]
+ SeqMonoid[A]
}
private[instances] trait SeqInstances1 extends SeqInstances2 {
@@ -47,6 +70,7 @@ class SeqEq[A](implicit ev: Eq[A]) extends Eq[Seq[A]] {
else StaticMethods.iteratorEq(xs.iterator, ys.iterator)
}
+@deprecated("Use SeqMonoid.apply, which does not allocate a new instance", "2.9.0")
class SeqMonoid[A] extends Monoid[Seq[A]] {
def empty: Seq[A] = Seq.empty
def combine(x: Seq[A], y: Seq[A]): Seq[A] = x ++ y
@@ -57,3 +81,11 @@ class SeqMonoid[A] extends Monoid[Seq[A]] {
override def combineAll(xs: IterableOnce[Seq[A]]): Seq[A] =
StaticMethods.combineAllIterable(Seq.newBuilder[A], xs)
}
+
+object SeqMonoid {
+ @nowarn("cat=deprecation")
+ private[this] val singleton: Monoid[Seq[Any]] = new SeqMonoid[Any]
+
+ @nowarn("cat=deprecation")
+ def apply[A]: SeqMonoid[A] = singleton.asInstanceOf[SeqMonoid[A]]
+}
diff --git a/kernel/src/main/scala/cats/kernel/instances/SetInstances.scala b/kernel/src/main/scala/cats/kernel/instances/SetInstances.scala
index fb9add7d6e..837172753d 100644
--- a/kernel/src/main/scala/cats/kernel/instances/SetInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/SetInstances.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/ShortInstances.scala b/kernel/src/main/scala/cats/kernel/instances/ShortInstances.scala
index 3893bb5fed..0775ae2c69 100644
--- a/kernel/src/main/scala/cats/kernel/instances/ShortInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/ShortInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait ShortInstances {
- implicit val catsKernelStdOrderForShort: Order[Short] with Hash[Short] with BoundedEnumerable[Short] = new ShortOrder
+ implicit val catsKernelStdOrderForShort: Order[Short] & Hash[Short] & BoundedEnumerable[Short] = new ShortOrder
implicit val catsKernelStdGroupForShort: CommutativeGroup[Short] = new ShortGroup
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/SortedMapInstances.scala b/kernel/src/main/scala/cats/kernel/instances/SortedMapInstances.scala
index 61ce5ea5f9..d0f851e777 100644
--- a/kernel/src/main/scala/cats/kernel/instances/SortedMapInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/SortedMapInstances.scala
@@ -1,9 +1,50 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* This file is derived in part from https://github.com/scala/scala/blob/v2.12.2/src/library/scala/util/hashing/MurmurHash3.scala
+ * Modified by Typelevel for redistribution in Cats.
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ * Scala
+ * Copyright (c) 2002-2022 EPFL
+ * Copyright (c) 2011-2022 Lightbend, Inc.
+ *
+ * Scala includes software developed at
+ * LAMP/EPFL (https://lamp.epfl.ch/) and
+ * Lightbend, Inc. (https://www.lightbend.com/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package cats.kernel
package instances
import scala.collection.immutable.SortedMap
-trait SortedMapInstances extends SortedMapInstances2 {
+trait SortedMapInstances extends SortedMapInstances3 {
implicit def catsKernelStdHashForSortedMap[K: Hash, V: Hash]: Hash[SortedMap[K, V]] =
new SortedMapHash[K, V]
@@ -35,6 +76,38 @@ private[instances] trait SortedMapInstances2 extends SortedMapInstances1 {
implicit def catsKernelStdMonoidForSortedMap[K: Order, V: Semigroup]: Monoid[SortedMap[K, V]] =
new SortedMapMonoid[K, V]
+
+ implicit def catsKernelStdPartialOrderForSortedMap[K, V: PartialOrder]: PartialOrder[SortedMap[K, V]] =
+ new SortedMapPartialOrder[K, V]
+}
+
+private[instances] trait SortedMapInstances3 extends SortedMapInstances2 {
+ implicit def catsKernelStdOrderForSortedMap[K, V: Order]: Order[SortedMap[K, V]] =
+ new SortedMapOrder[K, V]
+}
+
+private[instances] class SortedMapOrder[K, V](implicit V: Order[V]) extends Order[SortedMap[K, V]] {
+ override def compare(x: SortedMap[K, V], y: SortedMap[K, V]): Int = {
+ implicit val order: Order[K] = Order.fromOrdering(x.ordering)
+ if (x eq y) {
+ 0
+ } else {
+ StaticMethods.iteratorCompare(x.iterator, y.iterator)
+ }
+ }
+}
+
+private[instances] class SortedMapPartialOrder[K, V](implicit V: PartialOrder[V])
+ extends PartialOrder[SortedMap[K, V]] {
+ override def partialCompare(x: SortedMap[K, V], y: SortedMap[K, V]): Double = {
+ implicit val order: Order[K] = Order.fromOrdering(x.ordering)
+
+ if (x eq y) {
+ 0.0
+ } else {
+ StaticMethods.iteratorPartialCompare(x.iterator, y.iterator)
+ }
+ }
}
class SortedMapHash[K, V](implicit V: Hash[V], K: Hash[K]) extends SortedMapEq[K, V]()(V) with Hash[SortedMap[K, V]] {
diff --git a/kernel/src/main/scala/cats/kernel/instances/SortedSetInstances.scala b/kernel/src/main/scala/cats/kernel/instances/SortedSetInstances.scala
index 63913b59f7..553b2dde71 100644
--- a/kernel/src/main/scala/cats/kernel/instances/SortedSetInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/SortedSetInstances.scala
@@ -1,3 +1,44 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* This file is derived in part from https://github.com/scala/scala/blob/v2.12.2/src/library/scala/util/hashing/MurmurHash3.scala
+ * Modified by Typelevel for redistribution in Cats.
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ * Scala
+ * Copyright (c) 2002-2022 EPFL
+ * Copyright (c) 2011-2022 Lightbend, Inc.
+ *
+ * Scala includes software developed at
+ * LAMP/EPFL (https://lamp.epfl.ch/) and
+ * Lightbend, Inc. (https://www.lightbend.com/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/StaticMethods.scala b/kernel/src/main/scala/cats/kernel/instances/StaticMethods.scala
index e9e561f41d..140df84b43 100644
--- a/kernel/src/main/scala/cats/kernel/instances/StaticMethods.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/StaticMethods.scala
@@ -1,3 +1,44 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* This file is derived in part from https://github.com/scala/scala/blob/v2.12.2/src/library/scala/util/hashing/MurmurHash3.scala
+ * Modified by Typelevel for redistribution in Cats.
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ * Scala
+ * Copyright (c) 2002-2022 EPFL
+ * Copyright (c) 2011-2022 Lightbend, Inc.
+ *
+ * Scala includes software developed at
+ * LAMP/EPFL (https://lamp.epfl.ch/) and
+ * Lightbend, Inc. (https://www.lightbend.com/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package cats
package kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/StringInstances.scala b/kernel/src/main/scala/cats/kernel/instances/StringInstances.scala
index fdd5a31913..f8554a2ea4 100644
--- a/kernel/src/main/scala/cats/kernel/instances/StringInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/StringInstances.scala
@@ -1,9 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
import compat.scalaVersionSpecific._
@suppressUnusedImportWarningForScalaVersionSpecific
trait StringInstances {
- implicit val catsKernelStdOrderForString: Order[String] with Hash[String] with LowerBounded[String] = new StringOrder
+ implicit val catsKernelStdOrderForString: Order[String] & Hash[String] & LowerBounded[String] = new StringOrder
implicit val catsKernelStdMonoidForString: Monoid[String] = new StringMonoid
}
@@ -44,6 +65,6 @@ class StringMonoid extends Monoid[String] { self =>
self.combineAll(revStrings)
}
- override def reverse = self
+ override def reverse: Monoid[String] = self
}
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/SymbolInstances.scala b/kernel/src/main/scala/cats/kernel/instances/SymbolInstances.scala
index 6cfbfae59a..9d5ffba876 100644
--- a/kernel/src/main/scala/cats/kernel/instances/SymbolInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/SymbolInstances.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
trait SymbolInstances {
- implicit val catsKernelStdOrderForSymbol: Order[Symbol] with Hash[Symbol] with LowerBounded[Symbol] = new SymbolOrder
+ implicit val catsKernelStdOrderForSymbol: Order[Symbol] & Hash[Symbol] & LowerBounded[Symbol] = new SymbolOrder
}
trait SymbolLowerBounded extends LowerBounded[Symbol] {
diff --git a/kernel/src/main/scala/cats/kernel/instances/UUIDInstances.scala b/kernel/src/main/scala/cats/kernel/instances/UUIDInstances.scala
index 4b8cf0b874..62fbaec5f5 100644
--- a/kernel/src/main/scala/cats/kernel/instances/UUIDInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/UUIDInstances.scala
@@ -1,10 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
import java.util.UUID
trait UUIDInstances {
- implicit val catsKernelStdOrderForUUID: Order[UUID] with Hash[UUID] with LowerBounded[UUID] with UpperBounded[UUID] =
+ implicit val catsKernelStdOrderForUUID: Order[UUID] & Hash[UUID] & LowerBounded[UUID] & UpperBounded[UUID] =
new Order[UUID] with Hash[UUID] with UUIDBounded { self =>
def compare(x: UUID, y: UUID): Int = x.compareTo(y)
def hash(x: UUID): Int = x.hashCode()
diff --git a/kernel/src/main/scala/cats/kernel/instances/UnitInstances.scala b/kernel/src/main/scala/cats/kernel/instances/UnitInstances.scala
index f5f7ea1a43..bd6b3a7ad9 100644
--- a/kernel/src/main/scala/cats/kernel/instances/UnitInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/UnitInstances.scala
@@ -1,13 +1,34 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
import compat.scalaVersionSpecific._
@suppressUnusedImportWarningForScalaVersionSpecific
trait UnitInstances {
- implicit val catsKernelStdOrderForUnit: Order[Unit] with Hash[Unit] with BoundedEnumerable[Unit] =
+ implicit val catsKernelStdOrderForUnit: Order[Unit] & Hash[Unit] & BoundedEnumerable[Unit] =
new UnitOrder
- implicit val catsKernelStdAlgebraForUnit: BoundedSemilattice[Unit] with CommutativeGroup[Unit] =
+ implicit val catsKernelStdAlgebraForUnit: BoundedSemilattice[Unit] & CommutativeGroup[Unit] =
new UnitAlgebra
}
diff --git a/kernel/src/main/scala/cats/kernel/instances/VectorInstances.scala b/kernel/src/main/scala/cats/kernel/instances/VectorInstances.scala
index 75193a7e64..175d59f880 100644
--- a/kernel/src/main/scala/cats/kernel/instances/VectorInstances.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/VectorInstances.scala
@@ -1,13 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
import compat.scalaVersionSpecific._
+import scala.annotation.nowarn
+
@suppressUnusedImportWarningForScalaVersionSpecific
trait VectorInstances extends VectorInstances1 {
implicit def catsKernelStdOrderForVector[A: Order]: Order[Vector[A]] =
new VectorOrder[A]
implicit def catsKernelStdMonoidForVector[A]: Monoid[Vector[A]] =
- new VectorMonoid[A]
+ VectorMonoid[A]
}
private[instances] trait VectorInstances1 extends VectorInstances2 {
@@ -45,6 +68,7 @@ class VectorEq[A](implicit ev: Eq[A]) extends Eq[Vector[A]] {
else StaticMethods.iteratorEq(xs.iterator, ys.iterator)
}
+@deprecated("Use VectorMonoid.apply, which does not allocate a new instance", "2.9.0")
class VectorMonoid[A] extends Monoid[Vector[A]] {
def empty: Vector[A] = Vector.empty
def combine(x: Vector[A], y: Vector[A]): Vector[A] = x ++ y
@@ -55,3 +79,10 @@ class VectorMonoid[A] extends Monoid[Vector[A]] {
override def combineAll(xs: IterableOnce[Vector[A]]): Vector[A] =
StaticMethods.combineAllIterable(Vector.newBuilder[A], xs)
}
+
+object VectorMonoid {
+ @nowarn("msg=deprecated")
+ private[this] val singleton: Monoid[Vector[Any]] = new VectorMonoid[Any]
+
+ def apply[A]: Monoid[Vector[A]] = singleton.asInstanceOf[Monoid[Vector[A]]]
+}
diff --git a/kernel/src/main/scala/cats/kernel/instances/all/package.scala b/kernel/src/main/scala/cats/kernel/instances/all/package.scala
index f51831410c..ab6901c941 100644
--- a/kernel/src/main/scala/cats/kernel/instances/all/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/all/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/bigDecimal/package.scala b/kernel/src/main/scala/cats/kernel/instances/bigDecimal/package.scala
index 1f1479ffdc..a27da86985 100644
--- a/kernel/src/main/scala/cats/kernel/instances/bigDecimal/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/bigDecimal/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/bigInt/package.scala b/kernel/src/main/scala/cats/kernel/instances/bigInt/package.scala
index 581d72fb98..ab24a218e9 100644
--- a/kernel/src/main/scala/cats/kernel/instances/bigInt/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/bigInt/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/bitSet/package.scala b/kernel/src/main/scala/cats/kernel/instances/bitSet/package.scala
index 8101470743..eec2ea6e09 100644
--- a/kernel/src/main/scala/cats/kernel/instances/bitSet/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/bitSet/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/boolean/package.scala b/kernel/src/main/scala/cats/kernel/instances/boolean/package.scala
index 72b2dddcf7..f7691e14bb 100644
--- a/kernel/src/main/scala/cats/kernel/instances/boolean/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/boolean/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/byte/package.scala b/kernel/src/main/scala/cats/kernel/instances/byte/package.scala
index 81c00be595..1c59f96230 100644
--- a/kernel/src/main/scala/cats/kernel/instances/byte/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/byte/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/char/package.scala b/kernel/src/main/scala/cats/kernel/instances/char/package.scala
index 321b5ec48f..a6595dcd80 100644
--- a/kernel/src/main/scala/cats/kernel/instances/char/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/char/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/deadline/package.scala b/kernel/src/main/scala/cats/kernel/instances/deadline/package.scala
index e8316f91e2..c6ce69505a 100644
--- a/kernel/src/main/scala/cats/kernel/instances/deadline/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/deadline/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/double/package.scala b/kernel/src/main/scala/cats/kernel/instances/double/package.scala
index 2f94b36bc7..c6ebb98251 100644
--- a/kernel/src/main/scala/cats/kernel/instances/double/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/double/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/duration/package.scala b/kernel/src/main/scala/cats/kernel/instances/duration/package.scala
index c0b42054fe..b11cbf0554 100644
--- a/kernel/src/main/scala/cats/kernel/instances/duration/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/duration/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/either/package.scala b/kernel/src/main/scala/cats/kernel/instances/either/package.scala
index da52a4464d..2e055652b6 100644
--- a/kernel/src/main/scala/cats/kernel/instances/either/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/either/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/eq.scala b/kernel/src/main/scala/cats/kernel/instances/eq.scala
index 2ffbf559ad..21792e8a8b 100644
--- a/kernel/src/main/scala/cats/kernel/instances/eq.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/eq.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/finiteDuration/package.scala b/kernel/src/main/scala/cats/kernel/instances/finiteDuration/package.scala
index bb3ae7868c..69d8b53736 100644
--- a/kernel/src/main/scala/cats/kernel/instances/finiteDuration/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/finiteDuration/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/float/package.scala b/kernel/src/main/scala/cats/kernel/instances/float/package.scala
index c0c9e78c61..7f51e7b88f 100644
--- a/kernel/src/main/scala/cats/kernel/instances/float/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/float/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/function/package.scala b/kernel/src/main/scala/cats/kernel/instances/function/package.scala
index 2b9ed5c079..ba17df4567 100644
--- a/kernel/src/main/scala/cats/kernel/instances/function/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/function/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/hash.scala b/kernel/src/main/scala/cats/kernel/instances/hash.scala
index 3822096596..e2ffe72dde 100644
--- a/kernel/src/main/scala/cats/kernel/instances/hash.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/hash.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/int/package.scala b/kernel/src/main/scala/cats/kernel/instances/int/package.scala
index 52b75758f3..a6b11cbf81 100644
--- a/kernel/src/main/scala/cats/kernel/instances/int/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/int/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/list/package.scala b/kernel/src/main/scala/cats/kernel/instances/list/package.scala
index bbddec8bdc..72d2627dd8 100644
--- a/kernel/src/main/scala/cats/kernel/instances/list/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/list/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/long/package.scala b/kernel/src/main/scala/cats/kernel/instances/long/package.scala
index 424a64f063..c556b3845d 100644
--- a/kernel/src/main/scala/cats/kernel/instances/long/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/long/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/map/package.scala b/kernel/src/main/scala/cats/kernel/instances/map/package.scala
index 5d5b9db260..8b3fa52ca3 100644
--- a/kernel/src/main/scala/cats/kernel/instances/map/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/map/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/option/package.scala b/kernel/src/main/scala/cats/kernel/instances/option/package.scala
index b71553fe7e..15c79dbcab 100644
--- a/kernel/src/main/scala/cats/kernel/instances/option/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/option/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/order.scala b/kernel/src/main/scala/cats/kernel/instances/order.scala
index e678dc34d9..f47a5b1791 100644
--- a/kernel/src/main/scala/cats/kernel/instances/order.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/order.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/partialOrder.scala b/kernel/src/main/scala/cats/kernel/instances/partialOrder.scala
index b7dfc5819b..271bd18107 100644
--- a/kernel/src/main/scala/cats/kernel/instances/partialOrder.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/partialOrder.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/queue/package.scala b/kernel/src/main/scala/cats/kernel/instances/queue/package.scala
index 7cc23275e1..6513ec0b1f 100644
--- a/kernel/src/main/scala/cats/kernel/instances/queue/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/queue/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/seq/package.scala b/kernel/src/main/scala/cats/kernel/instances/seq/package.scala
index 9eb2cd5ba0..2b05e85077 100644
--- a/kernel/src/main/scala/cats/kernel/instances/seq/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/seq/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/set/package.scala b/kernel/src/main/scala/cats/kernel/instances/set/package.scala
index 86257fd0b9..1ebcb3d0df 100644
--- a/kernel/src/main/scala/cats/kernel/instances/set/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/set/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/short/package.scala b/kernel/src/main/scala/cats/kernel/instances/short/package.scala
index ad6d0d7ac2..aeef136fe0 100644
--- a/kernel/src/main/scala/cats/kernel/instances/short/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/short/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/sortedMap/package.scala b/kernel/src/main/scala/cats/kernel/instances/sortedMap/package.scala
index 737eef88db..7ab2c21614 100644
--- a/kernel/src/main/scala/cats/kernel/instances/sortedMap/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/sortedMap/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/sortedSet/package.scala b/kernel/src/main/scala/cats/kernel/instances/sortedSet/package.scala
index edddfb1011..b06c3c5e20 100644
--- a/kernel/src/main/scala/cats/kernel/instances/sortedSet/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/sortedSet/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/stream/package.scala b/kernel/src/main/scala/cats/kernel/instances/stream/package.scala
index 53bbfe510d..eeb72b3c24 100644
--- a/kernel/src/main/scala/cats/kernel/instances/stream/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/stream/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/string/package.scala b/kernel/src/main/scala/cats/kernel/instances/string/package.scala
index 61a311e74d..c39355ffc3 100644
--- a/kernel/src/main/scala/cats/kernel/instances/string/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/string/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/symbol/package.scala b/kernel/src/main/scala/cats/kernel/instances/symbol/package.scala
index 3093302f90..54e7f5e6e9 100644
--- a/kernel/src/main/scala/cats/kernel/instances/symbol/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/symbol/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/tuple/package.scala b/kernel/src/main/scala/cats/kernel/instances/tuple/package.scala
index 2572ef0e5f..279d47e244 100644
--- a/kernel/src/main/scala/cats/kernel/instances/tuple/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/tuple/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/unit/package.scala b/kernel/src/main/scala/cats/kernel/instances/unit/package.scala
index fe91a1bbca..001b7bb258 100644
--- a/kernel/src/main/scala/cats/kernel/instances/unit/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/unit/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/uuid/package.scala b/kernel/src/main/scala/cats/kernel/instances/uuid/package.scala
index c3fd236953..d630c7ccc3 100644
--- a/kernel/src/main/scala/cats/kernel/instances/uuid/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/uuid/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/kernel/src/main/scala/cats/kernel/instances/vector/package.scala b/kernel/src/main/scala/cats/kernel/instances/vector/package.scala
index d6d3164400..f91f8b4002 100644
--- a/kernel/src/main/scala/cats/kernel/instances/vector/package.scala
+++ b/kernel/src/main/scala/cats/kernel/instances/vector/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.kernel
package instances
diff --git a/laws/src/main/scala-2.12/cats/laws/discipline/ScalaVersionSpecific.scala b/laws/src/main/scala-2.12/cats/laws/discipline/ScalaVersionSpecific.scala
index 7280f132c7..f711747907 100644
--- a/laws/src/main/scala-2.12/cats/laws/discipline/ScalaVersionSpecific.scala
+++ b/laws/src/main/scala-2.12/cats/laws/discipline/ScalaVersionSpecific.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala-2.13+/cats/laws/discipline/ScalaVersionSpecific.scala b/laws/src/main/scala-2.13+/cats/laws/discipline/ScalaVersionSpecific.scala
index d385db2c45..f1e863e1e7 100644
--- a/laws/src/main/scala-2.13+/cats/laws/discipline/ScalaVersionSpecific.scala
+++ b/laws/src/main/scala-2.13+/cats/laws/discipline/ScalaVersionSpecific.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.laws.discipline
import cats.data.{NonEmptyLazyList, ZipLazyList, ZipStream}
diff --git a/laws/src/main/scala/cats/laws/AlignLaws.scala b/laws/src/main/scala/cats/laws/AlignLaws.scala
index 7d1d4c2428..490e266e75 100644
--- a/laws/src/main/scala/cats/laws/AlignLaws.scala
+++ b/laws/src/main/scala/cats/laws/AlignLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -24,6 +45,9 @@ trait AlignLaws[F[_]] {
def alignWithConsistent[A, B, C](fa: F[A], fb: F[B], f: A Ior B => C): IsEq[F[C]] =
fa.alignWith(fb)(f) <-> fa.align(fb).map(f)
+ def alignMergeWithConsistent[A](fa1: F[A], fa2: F[A], f: (A, A) => A): IsEq[F[A]] =
+ fa1.alignMergeWith(fa2)(f) <-> fa1.align(fa2).map(_.mergeWith(f))
+
private def assoc[A, B, C](x: Ior[A, Ior[B, C]]): Ior[Ior[A, B], C] =
x match {
case Left(a) => Left(Left(a))
diff --git a/laws/src/main/scala/cats/laws/AlternativeLaws.scala b/laws/src/main/scala/cats/laws/AlternativeLaws.scala
index 06b103f634..adb9cdfd99 100644
--- a/laws/src/main/scala/cats/laws/AlternativeLaws.scala
+++ b/laws/src/main/scala/cats/laws/AlternativeLaws.scala
@@ -1,7 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
import cats.syntax.all._
+import cats.kernel.compat.scalaVersionSpecific._
trait AlternativeLaws[F[_]] extends NonEmptyAlternativeLaws[F] with MonoidKLaws[F] {
implicit override def F: Alternative[F]
@@ -17,8 +39,13 @@ trait AlternativeLaws[F[_]] extends NonEmptyAlternativeLaws[F] with MonoidKLaws[
// Perhaps should be deprecated in favor of nonEmptyAlternativeRightDistributivity
def alternativeRightDistributivity[A, B](fa: F[A], ff: F[A => B], fg: F[A => B]): IsEq[F[B]] =
nonEmptyAlternativeRightDistributivity(fa, ff, fg)
+
+ def fromIterableOnce[A](as: Iterable[A]): IsEq[F[A]] =
+ F.fromIterableOnce(as) <-> F.combineAllK(as.iterator.map(F.pure(_)))
+
}
+@suppressUnusedImportWarningForScalaVersionSpecific
object AlternativeLaws {
def apply[F[_]](implicit ev: Alternative[F]): AlternativeLaws[F] =
new AlternativeLaws[F] { def F: Alternative[F] = ev }
diff --git a/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala b/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala
index 438acec347..458eff8af0 100644
--- a/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala
+++ b/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -40,11 +61,14 @@ trait ApplicativeErrorLaws[F[_], E] extends ApplicativeLaws[F] {
def attemptFromEitherConsistentWithPure[A](eab: Either[E, A]): IsEq[F[Either[E, A]]] =
F.attempt(F.fromEither(eab)) <-> F.pure(eab)
+ def voidErrorConsistentWithHandleError(fu: F[Unit]): IsEq[F[Unit]] =
+ F.voidError(fu) <-> F.handleError(fu)(Function.const(()))
+
def onErrorPure[A](a: A, f: E => F[Unit]): IsEq[F[A]] =
F.onError(F.pure(a)) { case x => f(x) } <-> F.pure(a)
def onErrorRaise[A](fa: F[A], e: E, fb: F[Unit]): IsEq[F[A]] =
- F.onError(F.raiseError[A](e)) { case err => fb } <-> F.map2(fb, F.raiseError[A](e))((_, b) => b)
+ F.onError(F.raiseError[A](e)) { case _ => fb } <-> F.map2(fb, F.raiseError[A](e))((_, b) => b)
def adaptErrorPure[A](a: A, f: E => E): IsEq[F[A]] =
F.adaptError(F.pure(a)) { case x => f(x) } <-> F.pure(a)
diff --git a/laws/src/main/scala/cats/laws/ApplicativeLaws.scala b/laws/src/main/scala/cats/laws/ApplicativeLaws.scala
index a1405f09a0..a0109f7d0f 100644
--- a/laws/src/main/scala/cats/laws/ApplicativeLaws.scala
+++ b/laws/src/main/scala/cats/laws/ApplicativeLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -38,14 +59,17 @@ trait ApplicativeLaws[F[_]] extends ApplyLaws[F] {
def applicativeUnit[A](a: A): IsEq[F[A]] =
F.unit.map(_ => a) <-> F.pure(a)
+ def replicateAVoidReplicateA_Consistent[A](n: Int, fa: F[A]): IsEq[F[Unit]] =
+ F.replicateA_(n, fa) <-> F.replicateA(n, fa).void
+
// The following are the lax monoidal functor identity laws - the associativity law is covered by
// Semigroupal's associativity law.
def monoidalLeftIdentity[A](fa: F[A]): (F[(Unit, A)], F[A]) =
- (F.product(F.pure(()), fa), fa)
+ (F.product(F.unit, fa), fa)
def monoidalRightIdentity[A](fa: F[A]): (F[(A, Unit)], F[A]) =
- (F.product(fa, F.pure(())), fa)
+ (F.product(fa, F.unit), fa)
}
object ApplicativeLaws {
diff --git a/laws/src/main/scala/cats/laws/ApplyLaws.scala b/laws/src/main/scala/cats/laws/ApplyLaws.scala
index 0d96699131..e32a8b5664 100644
--- a/laws/src/main/scala/cats/laws/ApplyLaws.scala
+++ b/laws/src/main/scala/cats/laws/ApplyLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/ArrowChoiceLaws.scala b/laws/src/main/scala/cats/laws/ArrowChoiceLaws.scala
index a465e37e18..2be4ba950f 100644
--- a/laws/src/main/scala/cats/laws/ArrowChoiceLaws.scala
+++ b/laws/src/main/scala/cats/laws/ArrowChoiceLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/ArrowLaws.scala b/laws/src/main/scala/cats/laws/ArrowLaws.scala
index 1e29e63d12..2326834905 100644
--- a/laws/src/main/scala/cats/laws/ArrowLaws.scala
+++ b/laws/src/main/scala/cats/laws/ArrowLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -38,7 +59,7 @@ trait ArrowLaws[F[_, _]] extends CategoryLaws[F] with StrongLaws[F] {
F.split(f, g) <-> (f.first.andThen(g.second))
def mergeConsistentWithAndThen[A, B, C](f: F[A, B], g: F[A, C]): IsEq[F[A, (B, C)]] =
- F.merge(f, g) <-> ((F.lift((x: A) => (x, x))).andThen(F.split(f, g)))
+ F.merge(f, g) <-> (F.lift((x: A) => (x, x)).andThen(F.split(f, g)))
private def fst[A, B](p: (A, B)): A = p._1
diff --git a/laws/src/main/scala/cats/laws/BifoldableLaws.scala b/laws/src/main/scala/cats/laws/BifoldableLaws.scala
index 3dc51233f2..b586e2fa61 100644
--- a/laws/src/main/scala/cats/laws/BifoldableLaws.scala
+++ b/laws/src/main/scala/cats/laws/BifoldableLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/BifunctorLaws.scala b/laws/src/main/scala/cats/laws/BifunctorLaws.scala
index 1304db1b39..ccdefc3d54 100644
--- a/laws/src/main/scala/cats/laws/BifunctorLaws.scala
+++ b/laws/src/main/scala/cats/laws/BifunctorLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.laws
import cats.Bifunctor
diff --git a/laws/src/main/scala/cats/laws/BimonadLaws.scala b/laws/src/main/scala/cats/laws/BimonadLaws.scala
index 244d51361c..aab44a7dba 100644
--- a/laws/src/main/scala/cats/laws/BimonadLaws.scala
+++ b/laws/src/main/scala/cats/laws/BimonadLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/BitraverseLaws.scala b/laws/src/main/scala/cats/laws/BitraverseLaws.scala
index d57eb69869..426f77a707 100644
--- a/laws/src/main/scala/cats/laws/BitraverseLaws.scala
+++ b/laws/src/main/scala/cats/laws/BitraverseLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/CategoryLaws.scala b/laws/src/main/scala/cats/laws/CategoryLaws.scala
index ea380c7c83..4adf359efe 100644
--- a/laws/src/main/scala/cats/laws/CategoryLaws.scala
+++ b/laws/src/main/scala/cats/laws/CategoryLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/ChoiceLaws.scala b/laws/src/main/scala/cats/laws/ChoiceLaws.scala
index 3f083625d5..83743a4e17 100644
--- a/laws/src/main/scala/cats/laws/ChoiceLaws.scala
+++ b/laws/src/main/scala/cats/laws/ChoiceLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/CoflatMapLaws.scala b/laws/src/main/scala/cats/laws/CoflatMapLaws.scala
index eaf6bfaf71..b3c4c5c3f2 100644
--- a/laws/src/main/scala/cats/laws/CoflatMapLaws.scala
+++ b/laws/src/main/scala/cats/laws/CoflatMapLaws.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
import cats.data.Cokleisli
-import cats.implicits._
+import cats.syntax.all._
/**
* Laws that must be obeyed by any `CoflatMap`.
@@ -28,7 +49,7 @@ trait CoflatMapLaws[F[_]] extends FunctorLaws[F] {
*/
def cokleisliAssociativity[A, B, C, D](f: F[A] => B, g: F[B] => C, h: F[C] => D, fa: F[A]): IsEq[D] = {
val (cf, cg, ch) = (Cokleisli(f), Cokleisli(g), Cokleisli(h))
- (cf.andThen(cg)).andThen(ch).run(fa) <-> cf.andThen(cg.andThen(ch)).run(fa)
+ cf.andThen(cg).andThen(ch).run(fa) <-> cf.andThen(cg.andThen(ch)).run(fa)
}
}
diff --git a/laws/src/main/scala/cats/laws/CommutativeApplicativeLaws.scala b/laws/src/main/scala/cats/laws/CommutativeApplicativeLaws.scala
index 05f9770312..be2021f523 100644
--- a/laws/src/main/scala/cats/laws/CommutativeApplicativeLaws.scala
+++ b/laws/src/main/scala/cats/laws/CommutativeApplicativeLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.laws
import cats.CommutativeApplicative
diff --git a/laws/src/main/scala/cats/laws/CommutativeApplyLaws.scala b/laws/src/main/scala/cats/laws/CommutativeApplyLaws.scala
index 19536c982b..3ed4b84caf 100644
--- a/laws/src/main/scala/cats/laws/CommutativeApplyLaws.scala
+++ b/laws/src/main/scala/cats/laws/CommutativeApplyLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.laws
import cats.CommutativeApply
diff --git a/laws/src/main/scala/cats/laws/CommutativeArrowLaws.scala b/laws/src/main/scala/cats/laws/CommutativeArrowLaws.scala
index 61ead19bdd..95b324b98b 100644
--- a/laws/src/main/scala/cats/laws/CommutativeArrowLaws.scala
+++ b/laws/src/main/scala/cats/laws/CommutativeArrowLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/CommutativeFlatMapLaws.scala b/laws/src/main/scala/cats/laws/CommutativeFlatMapLaws.scala
index 04b5a19aba..c042ae2573 100644
--- a/laws/src/main/scala/cats/laws/CommutativeFlatMapLaws.scala
+++ b/laws/src/main/scala/cats/laws/CommutativeFlatMapLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/CommutativeMonadLaws.scala b/laws/src/main/scala/cats/laws/CommutativeMonadLaws.scala
index 509d046db8..595ca02cd9 100644
--- a/laws/src/main/scala/cats/laws/CommutativeMonadLaws.scala
+++ b/laws/src/main/scala/cats/laws/CommutativeMonadLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/ComonadLaws.scala b/laws/src/main/scala/cats/laws/ComonadLaws.scala
index b459a49109..5008253717 100644
--- a/laws/src/main/scala/cats/laws/ComonadLaws.scala
+++ b/laws/src/main/scala/cats/laws/ComonadLaws.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
import cats.data.Cokleisli
-import cats.implicits._
+import cats.syntax.all._
/**
* Laws that must be obeyed by any `Comonad`.
diff --git a/laws/src/main/scala/cats/laws/ComposeLaws.scala b/laws/src/main/scala/cats/laws/ComposeLaws.scala
index c1d14e546f..1d98c4e86e 100644
--- a/laws/src/main/scala/cats/laws/ComposeLaws.scala
+++ b/laws/src/main/scala/cats/laws/ComposeLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -11,7 +32,7 @@ trait ComposeLaws[F[_, _]] {
implicit def F: Compose[F]
def composeAssociativity[A, B, C, D](fab: F[A, B], fbc: F[B, C], fcd: F[C, D]): IsEq[F[A, D]] =
- ((fab.andThen(fbc)).andThen(fcd)) <-> (fab.andThen(fbc.andThen(fcd)))
+ (fab.andThen(fbc).andThen(fcd)) <-> (fab.andThen(fbc.andThen(fcd)))
}
object ComposeLaws {
diff --git a/laws/src/main/scala/cats/laws/ContravariantLaws.scala b/laws/src/main/scala/cats/laws/ContravariantLaws.scala
index 4b325a4d3e..39f14e0250 100644
--- a/laws/src/main/scala/cats/laws/ContravariantLaws.scala
+++ b/laws/src/main/scala/cats/laws/ContravariantLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala b/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala
index db55d2e247..e4d5cd09aa 100644
--- a/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala
+++ b/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/ContravariantSemigroupalLaws.scala b/laws/src/main/scala/cats/laws/ContravariantSemigroupalLaws.scala
index 4ba3a6990d..4dfef80bb4 100644
--- a/laws/src/main/scala/cats/laws/ContravariantSemigroupalLaws.scala
+++ b/laws/src/main/scala/cats/laws/ContravariantSemigroupalLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/DeferLaws.scala b/laws/src/main/scala/cats/laws/DeferLaws.scala
index 1317460ad0..ab9118743a 100644
--- a/laws/src/main/scala/cats/laws/DeferLaws.scala
+++ b/laws/src/main/scala/cats/laws/DeferLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -14,7 +35,7 @@ trait DeferLaws[F[_]] {
def deferDoesNotEvaluate[A](fa: Unit => F[A]): IsEq[Boolean] = {
var evaluated = false
- val deferUnit = F.defer {
+ val _ = F.defer {
evaluated = true;
fa(())
}
diff --git a/laws/src/main/scala/cats/laws/DistributiveLaws.scala b/laws/src/main/scala/cats/laws/DistributiveLaws.scala
index 9bb7f2ab2f..85f603e0ea 100644
--- a/laws/src/main/scala/cats/laws/DistributiveLaws.scala
+++ b/laws/src/main/scala/cats/laws/DistributiveLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/FlatMapLaws.scala b/laws/src/main/scala/cats/laws/FlatMapLaws.scala
index be776d1dc1..4e1bb1a10f 100644
--- a/laws/src/main/scala/cats/laws/FlatMapLaws.scala
+++ b/laws/src/main/scala/cats/laws/FlatMapLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -24,7 +45,7 @@ trait FlatMapLaws[F[_]] extends ApplyLaws[F] {
*/
def kleisliAssociativity[A, B, C, D](f: A => F[B], g: B => F[C], h: C => F[D], a: A): IsEq[F[D]] = {
val (kf, kg, kh) = (Kleisli(f), Kleisli(g), Kleisli(h))
- (kf.andThen(kg)).andThen(kh).run(a) <-> kf.andThen(kg.andThen(kh)).run(a)
+ kf.andThen(kg).andThen(kh).run(a) <-> kf.andThen(kg.andThen(kh)).run(a)
}
def mproductConsistency[A, B](fa: F[A], fb: A => F[B]): IsEq[F[(A, B)]] =
diff --git a/laws/src/main/scala/cats/laws/FoldableLaws.scala b/laws/src/main/scala/cats/laws/FoldableLaws.scala
index 981e686b80..c8c38d15c0 100644
--- a/laws/src/main/scala/cats/laws/FoldableLaws.scala
+++ b/laws/src/main/scala/cats/laws/FoldableLaws.scala
@@ -1,7 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
-import cats.implicits._
+import cats.syntax.all._
import scala.collection.mutable
@@ -125,7 +146,7 @@ trait FoldableLaws[F[_]] extends UnorderedFoldableLaws[F] {
F.collectFirst(fa)(pf) <-> F.collectFirstSome(fa)(pf.lift)
def orderedConsistency[A: Eq](x: F[A], y: F[A])(implicit ev: Eq[F[A]]): IsEq[List[A]] =
- if (x === y) (F.toList(x) <-> F.toList(y))
+ if (x === y) F.toList(x) <-> F.toList(y)
else List.empty[A] <-> List.empty[A]
}
diff --git a/laws/src/main/scala/cats/laws/FunctorFilterLaws.scala b/laws/src/main/scala/cats/laws/FunctorFilterLaws.scala
index 73e48f8dec..8c9d15bae0 100644
--- a/laws/src/main/scala/cats/laws/FunctorFilterLaws.scala
+++ b/laws/src/main/scala/cats/laws/FunctorFilterLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/FunctorLaws.scala b/laws/src/main/scala/cats/laws/FunctorLaws.scala
index 1f9f163333..d7044675ff 100644
--- a/laws/src/main/scala/cats/laws/FunctorLaws.scala
+++ b/laws/src/main/scala/cats/laws/FunctorLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -12,6 +33,9 @@ trait FunctorLaws[F[_]] extends InvariantLaws[F] {
def covariantIdentity[A](fa: F[A]): IsEq[F[A]] =
fa.map(identity) <-> fa
+ def mapOrKeepToMapEquivalence[A, A1 >: A](fa: F[A], pf: PartialFunction[A, A1]): IsEq[F[A1]] =
+ fa.mapOrKeep(pf) <-> fa.map(a => pf.applyOrElse(a, identity[A1]))
+
def covariantComposition[A, B, C](fa: F[A], f: A => B, g: B => C): IsEq[F[C]] =
fa.map(f).map(g) <-> fa.map(f.andThen(g))
}
diff --git a/laws/src/main/scala/cats/laws/InjectKLaws.scala b/laws/src/main/scala/cats/laws/InjectKLaws.scala
index b5b77c90b1..9298686009 100644
--- a/laws/src/main/scala/cats/laws/InjectKLaws.scala
+++ b/laws/src/main/scala/cats/laws/InjectKLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/InjectLaws.scala b/laws/src/main/scala/cats/laws/InjectLaws.scala
index 956793698b..26556eebdc 100644
--- a/laws/src/main/scala/cats/laws/InjectLaws.scala
+++ b/laws/src/main/scala/cats/laws/InjectLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/InvariantLaws.scala b/laws/src/main/scala/cats/laws/InvariantLaws.scala
index 4718b45b44..65920fcc05 100644
--- a/laws/src/main/scala/cats/laws/InvariantLaws.scala
+++ b/laws/src/main/scala/cats/laws/InvariantLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala b/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala
index 58c82d4766..782777be58 100644
--- a/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala
+++ b/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/InvariantSemigroupalLaws.scala b/laws/src/main/scala/cats/laws/InvariantSemigroupalLaws.scala
index b15a7cea91..216c2a06c5 100644
--- a/laws/src/main/scala/cats/laws/InvariantSemigroupalLaws.scala
+++ b/laws/src/main/scala/cats/laws/InvariantSemigroupalLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/MonadErrorLaws.scala b/laws/src/main/scala/cats/laws/MonadErrorLaws.scala
index c05f029994..6071474db0 100644
--- a/laws/src/main/scala/cats/laws/MonadErrorLaws.scala
+++ b/laws/src/main/scala/cats/laws/MonadErrorLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/MonadLaws.scala b/laws/src/main/scala/cats/laws/MonadLaws.scala
index b488192ae6..38ca928247 100644
--- a/laws/src/main/scala/cats/laws/MonadLaws.scala
+++ b/laws/src/main/scala/cats/laws/MonadLaws.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
import cats.data.Kleisli
-import cats.implicits._
+import cats.syntax.all._
/**
* Laws that must be obeyed by any `Monad`.
@@ -36,6 +57,12 @@ trait MonadLaws[F[_]] extends ApplicativeLaws[F] with FlatMapLaws[F] {
def mapFlatMapCoherence[A, B](fa: F[A], f: A => B): IsEq[F[B]] =
fa.flatMap(a => F.pure(f(a))) <-> fa.map(f)
+ /**
+ * Make sure that flatMapOrKeep and flatMap are consistent.
+ */
+ def flatMapOrKeepToFlatMapCoherence[A, A1 >: A](fa: F[A], pfa: PartialFunction[A, F[A1]]): IsEq[F[A1]] =
+ F.flatMapOrKeep[A, A1](fa)(pfa) <-> F.flatMap(fa)(a => pfa.applyOrElse(a, F.pure[A1]))
+
lazy val tailRecMStackSafety: IsEq[F[Int]] = {
val n = 50000
val res = F.tailRecM(0)(i => F.pure(if (i < n) Either.left(i + 1) else Either.right(i)))
diff --git a/laws/src/main/scala/cats/laws/MonoidKLaws.scala b/laws/src/main/scala/cats/laws/MonoidKLaws.scala
index e8ad9251ec..aecea5b7f3 100644
--- a/laws/src/main/scala/cats/laws/MonoidKLaws.scala
+++ b/laws/src/main/scala/cats/laws/MonoidKLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -12,6 +33,18 @@ trait MonoidKLaws[F[_]] extends SemigroupKLaws[F] {
def monoidKRightIdentity[A](a: F[A]): IsEq[F[A]] =
F.combineK(a, F.empty) <-> a
+
+ def repeatK0[A](x: F[A]): IsEq[F[A]] =
+ F.combineNK(x, 0) <-> F.empty
+
+ def collectK0[A](x: A): IsEq[F[A]] =
+ F.combineAllK(Nil) <-> F.empty
+
+ def combineAllK[A](xs: Vector[F[A]]): IsEq[F[A]] =
+ F.combineAllK(xs) <-> (F.empty[A] +: xs).reduce(F.combineK[A])
+
+ def isId[A](x: F[A], eqv: Eq[F[A]]): IsEq[Boolean] =
+ eqv.eqv(x, F.empty) <-> F.isEmpty(x)(eqv)
}
object MonoidKLaws {
diff --git a/laws/src/main/scala/cats/laws/NonEmptyAlternativeLaws.scala b/laws/src/main/scala/cats/laws/NonEmptyAlternativeLaws.scala
index 7303afc5f5..413585c79c 100644
--- a/laws/src/main/scala/cats/laws/NonEmptyAlternativeLaws.scala
+++ b/laws/src/main/scala/cats/laws/NonEmptyAlternativeLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/NonEmptyParallelLaws.scala b/laws/src/main/scala/cats/laws/NonEmptyParallelLaws.scala
index 880b3ba1d9..7eef4239b4 100644
--- a/laws/src/main/scala/cats/laws/NonEmptyParallelLaws.scala
+++ b/laws/src/main/scala/cats/laws/NonEmptyParallelLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/NonEmptyTraverseLaws.scala b/laws/src/main/scala/cats/laws/NonEmptyTraverseLaws.scala
index e89d7d4ac5..8530ed9ef9 100644
--- a/laws/src/main/scala/cats/laws/NonEmptyTraverseLaws.scala
+++ b/laws/src/main/scala/cats/laws/NonEmptyTraverseLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.laws
import cats.{Apply, Id, NonEmptyTraverse, Semigroup}
diff --git a/laws/src/main/scala/cats/laws/ParallelLaws.scala b/laws/src/main/scala/cats/laws/ParallelLaws.scala
index 4e7165e94a..67c4ee9d49 100644
--- a/laws/src/main/scala/cats/laws/ParallelLaws.scala
+++ b/laws/src/main/scala/cats/laws/ParallelLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/ProfunctorLaws.scala b/laws/src/main/scala/cats/laws/ProfunctorLaws.scala
index 904b5344a1..e1b83a4b5d 100644
--- a/laws/src/main/scala/cats/laws/ProfunctorLaws.scala
+++ b/laws/src/main/scala/cats/laws/ProfunctorLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/ReducibleLaws.scala b/laws/src/main/scala/cats/laws/ReducibleLaws.scala
index 7c3fe2e417..8acd33462d 100644
--- a/laws/src/main/scala/cats/laws/ReducibleLaws.scala
+++ b/laws/src/main/scala/cats/laws/ReducibleLaws.scala
@@ -1,7 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
-import cats.implicits._
+import cats.syntax.all._
trait ReducibleLaws[F[_]] extends FoldableLaws[F] {
implicit def F: Reducible[F]
@@ -33,10 +54,10 @@ trait ReducibleLaws[F[_]] extends FoldableLaws[F] {
fa.reduce <-> fa.reduceLeft(B.combine)
def traverseConsistent[G[_]: Applicative, A, B](fa: F[A], f: A => G[B]): IsEq[G[Unit]] =
- fa.nonEmptyTraverse_(f) <-> fa.traverse_(f)
+ fa.nonEmptyTraverseVoid(f) <-> fa.traverseVoid(f)
def sequenceConsistent[G[_]: Applicative, A](fa: F[G[A]]): IsEq[G[Unit]] =
- fa.nonEmptySequence_ <-> fa.sequence_
+ fa.nonEmptySequenceVoid <-> fa.sequenceVoid
def sizeConsistent[A](fa: F[A]): IsEq[Long] =
fa.size <-> fa.reduceMap(_ => 1L)
diff --git a/laws/src/main/scala/cats/laws/RepresentableLaws.scala b/laws/src/main/scala/cats/laws/RepresentableLaws.scala
index a5758ce335..939c697dd3 100644
--- a/laws/src/main/scala/cats/laws/RepresentableLaws.scala
+++ b/laws/src/main/scala/cats/laws/RepresentableLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/SemigroupKLaws.scala b/laws/src/main/scala/cats/laws/SemigroupKLaws.scala
index 34cd1792ce..bbafde4133 100644
--- a/laws/src/main/scala/cats/laws/SemigroupKLaws.scala
+++ b/laws/src/main/scala/cats/laws/SemigroupKLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -9,6 +30,34 @@ trait SemigroupKLaws[F[_]] {
def semigroupKAssociative[A](a: F[A], b: F[A], c: F[A]): IsEq[F[A]] =
F.combineK(F.combineK(a, b), c) <-> F.combineK(a, F.combineK(b, c))
+
+ def repeat1K[A](a: F[A]): IsEq[F[A]] =
+ F.combineNK(a, 1) <-> a
+
+ def repeat2K[A](a: F[A]): IsEq[F[A]] =
+ F.combineNK(a, 2) <-> F.combineK(a, a)
+
+ def combineAllOptionK[A](xs: Vector[F[A]]): IsEq[Option[F[A]]] =
+ F.combineAllOptionK(xs) <-> xs.reduceOption(F.combineK[A])
+
+ def reverseReversesK[A](a: F[A], b: F[A]): IsEq[F[A]] =
+ F.combineK(a, b) <-> F.reverse.combineK(b, a)
+
+ def reverseRepeat1K[A](a: F[A]): IsEq[F[A]] = {
+ val rev = F.reverse
+ rev.combineNK(a, 1) <-> a
+ }
+
+ def reverseRepeat2K[A](a: F[A]): IsEq[F[A]] = {
+ val rev = F.reverse
+ rev.combineNK(a, 2) <-> rev.combineK(a, a)
+ }
+
+ def reverseCombineAllOptionK[A](xs: Vector[F[A]]): IsEq[Option[F[A]]] = {
+ val rev = F.reverse
+ rev.combineAllOptionK(xs) <-> xs.reduceOption(rev.combineK[A])
+ }
+
}
object SemigroupKLaws {
diff --git a/laws/src/main/scala/cats/laws/SemigroupalLaws.scala b/laws/src/main/scala/cats/laws/SemigroupalLaws.scala
index 59cdbc363f..444c3ccdea 100644
--- a/laws/src/main/scala/cats/laws/SemigroupalLaws.scala
+++ b/laws/src/main/scala/cats/laws/SemigroupalLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/ShortCircuitingLaws.scala b/laws/src/main/scala/cats/laws/ShortCircuitingLaws.scala
index ca8e0c4d22..52838ddb74 100644
--- a/laws/src/main/scala/cats/laws/ShortCircuitingLaws.scala
+++ b/laws/src/main/scala/cats/laws/ShortCircuitingLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.laws
import java.util.concurrent.atomic.AtomicLong
@@ -14,7 +35,7 @@ trait ShortCircuitingLaws[F[_]] {
def foldMapKShortCircuits[A](fa: F[A], empty: A)(implicit F: Foldable[F]): IsEq[Long] = {
val size = fa.size
val maxInvocationsAllowed = size / 2
- val f = new RestrictedFunction[A, Option[A]]((a: A) => None, maxInvocationsAllowed, Some(empty))
+ val f = new RestrictedFunction[A, Option[A]](Function.const(None), maxInvocationsAllowed, Some(empty))
fa.foldMapK(f)
f.invocations.get <-> (maxInvocationsAllowed + 1).min(size)
@@ -23,7 +44,7 @@ trait ShortCircuitingLaws[F[_]] {
def foldMapKWontShortCircuit[A](fa: F[A], empty: A)(implicit F: Foldable[F]): IsEq[Long] = {
val size = fa.size
val maxInvocationsAllowed = size / 2
- val f = new RestrictedFunction[A, Option[A]]((a: A) => None, maxInvocationsAllowed, Some(empty))
+ val f = new RestrictedFunction[A, Option[A]](Function.const(None), maxInvocationsAllowed, Some(empty))
fa.foldMapK(f)(F, nonShortCircuitingMonoidK)
f.invocations.get <-> size
diff --git a/laws/src/main/scala/cats/laws/StrongLaws.scala b/laws/src/main/scala/cats/laws/StrongLaws.scala
index 4beee5b641..30ea52a057 100644
--- a/laws/src/main/scala/cats/laws/StrongLaws.scala
+++ b/laws/src/main/scala/cats/laws/StrongLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/TraverseFilterLaws.scala b/laws/src/main/scala/cats/laws/TraverseFilterLaws.scala
index 3c45188ddd..f4dc4040e5 100644
--- a/laws/src/main/scala/cats/laws/TraverseFilterLaws.scala
+++ b/laws/src/main/scala/cats/laws/TraverseFilterLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -31,6 +52,14 @@ trait TraverseFilterLaws[F[_]] extends FunctorFilterLaws[F] {
G: Monad[G]
): IsEq[G[F[B]]] =
fa.traverseEither(a => f(a).map(_.toRight(e)))((_, _) => Applicative[G].unit) <-> fa.traverseFilter(f)
+
+ def traverseCollectRef[G[_], A, B](fa: F[A], f: PartialFunction[A, G[B]])(implicit
+ G: Applicative[G]
+ ): IsEq[G[F[B]]] = {
+ val lhs = fa.traverseCollect(f)
+ val rhs = fa.traverseFilter(a => f.lift(a).sequence)
+ lhs <-> rhs
+ }
}
object TraverseFilterLaws {
diff --git a/laws/src/main/scala/cats/laws/TraverseLaws.scala b/laws/src/main/scala/cats/laws/TraverseLaws.scala
index 856e212392..d9ab4d84b6 100644
--- a/laws/src/main/scala/cats/laws/TraverseLaws.scala
+++ b/laws/src/main/scala/cats/laws/TraverseLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -85,6 +106,12 @@ trait TraverseLaws[F[_]] extends FunctorLaws[F] with FoldableLaws[F] with Unorde
first <-> traverseFirst
}
+ def mapAccumulateRef[S, A, B](init: S, fa: F[A], f: (S, A) => (S, B)): IsEq[(S, F[B])] = {
+ val lhs = F.mapAccumulate(init, fa)(f)
+ val rhs = F.traverse(fa)(a => State(s => f(s, a))).run(init).value
+ lhs <-> rhs
+ }
+
def mapWithIndexRef[A, B](fa: F[A], f: (A, Int) => B): IsEq[F[B]] = {
val lhs = F.mapWithIndex(fa)(f)
val rhs = F.traverse(fa)(a => State((s: Int) => (s + 1, f(a, s)))).runA(0).value
@@ -102,6 +129,43 @@ trait TraverseLaws[F[_]] extends FunctorLaws[F] with FoldableLaws[F] with Unorde
val rhs = F.map(F.mapWithIndex(fa)((a, i) => (a, i)))(f)
lhs <-> rhs
}
+
+ def mapWithLongIndexRef[A, B](fa: F[A], f: (A, Long) => B): IsEq[F[B]] = {
+ val lhs = F.mapWithLongIndex(fa)(f)
+ val rhs = F.traverse(fa)(a => State((s: Long) => (s + 1, f(a, s)))).runA(0L).value
+ lhs <-> rhs
+ }
+
+ def traverseWithLongIndexMRef[G[_], A, B](fa: F[A], f: (A, Long) => G[B])(implicit G: Monad[G]): IsEq[G[F[B]]] = {
+ val lhs = F.traverseWithLongIndexM(fa)(f)
+ val rhs = F.traverse(fa)(a => StateT((s: Long) => G.map(f(a, s))(b => (s + 1, b)))).runA(0L)
+ lhs <-> rhs
+ }
+
+ def zipWithLongIndexRef[A, B](fa: F[A], f: ((A, Long)) => B): IsEq[F[B]] = {
+ val lhs = F.map(F.zipWithLongIndex(fa))(f)
+ val rhs = F.map(F.mapWithLongIndex(fa)((a, i) => (a, i)))(f)
+ lhs <-> rhs
+ }
+
+ def updatedRef[A, B >: A](fa: F[A], idx: Long, b: B): IsEq[Option[F[B]]] = {
+ val lhs = F.updated_(fa, idx, b)
+ val rhs =
+ if (idx < 0L)
+ None
+ else
+ F.mapAccumulate(0L, fa)((i, a) =>
+ if (i == idx)
+ (i + 1, b)
+ else
+ (i + 1, a)
+ ) match {
+ case (i, fb) if i > idx => Some(fb)
+ case _ => None
+ }
+
+ lhs <-> rhs
+ }
}
object TraverseLaws {
diff --git a/laws/src/main/scala/cats/laws/UnorderedFoldableLaws.scala b/laws/src/main/scala/cats/laws/UnorderedFoldableLaws.scala
index 45b765c7ee..e70df54e0c 100644
--- a/laws/src/main/scala/cats/laws/UnorderedFoldableLaws.scala
+++ b/laws/src/main/scala/cats/laws/UnorderedFoldableLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
@@ -9,9 +30,12 @@ trait UnorderedFoldableLaws[F[_]] {
def unorderedFoldConsistentWithUnorderedFoldMap[A: CommutativeMonoid](fa: F[A]): IsEq[A] =
F.unorderedFoldMap(fa)(identity) <-> F.unorderedFold(fa)
+ def unorderedFoldMapAIdentity[A, B: CommutativeMonoid](fa: F[A], f: A => B): IsEq[B] =
+ F.unorderedFoldMapA[Id, A, B](fa)(f) <-> F.unorderedFoldMap(fa)(f)
+
def forallConsistentWithExists[A](fa: F[A], p: A => Boolean): Boolean =
if (F.forall(fa)(p)) {
- val negationExists = F.exists(fa)(a => !(p(a)))
+ val negationExists = F.exists(fa)(a => !p(a))
// if p is true for all elements, then there cannot be an element for which
// it does not hold.
@@ -48,6 +72,14 @@ trait UnorderedFoldableLaws[F[_]] {
def nonEmptyRef[A](fa: F[A]): IsEq[Boolean] =
F.nonEmpty(fa) <-> !F.isEmpty(fa)
+ def containsConsistentWithExists[A](fa: F[A], v: A)(implicit eq: Eq[A]): IsEq[Boolean] =
+ F.contains_(fa, v) <-> F.exists(fa)(a => eq.eqv(a, v))
+
+ def containsConsistentWithForall[A](fa: F[A], v: A)(implicit eq: Eq[A]): IsEq[Boolean] =
+ !F.contains_(fa, v) <-> F.forall(fa)(a => eq.neqv(a, v))
+
+ def containsAllElementsFromItself[A](fa: F[A])(implicit eq: Eq[A]): Boolean =
+ F.forall(fa)(a => F.contains_(fa, a))
}
object UnorderedFoldableLaws {
diff --git a/laws/src/main/scala/cats/laws/UnorderedTraverseLaws.scala b/laws/src/main/scala/cats/laws/UnorderedTraverseLaws.scala
index d3a3ee1252..7a41a0fae7 100644
--- a/laws/src/main/scala/cats/laws/UnorderedTraverseLaws.scala
+++ b/laws/src/main/scala/cats/laws/UnorderedTraverseLaws.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/discipline/AlignTests.scala b/laws/src/main/scala/cats/laws/discipline/AlignTests.scala
index c7af3738be..f640349b74 100644
--- a/laws/src/main/scala/cats/laws/discipline/AlignTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/AlignTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -29,15 +50,13 @@ trait AlignTests[F[_]] extends Laws {
EqFIorCD: Eq[F[C Ior D]],
EqFAssoc: Eq[F[Ior[Ior[A, B], C]]]
): RuleSet =
- new DefaultRuleSet(name = "align",
- parent = None,
- "align associativity" -> forAll(laws.alignAssociativity[A, B, C] _),
- "align homomorphism" -> forAll { (fa: F[A], fb: F[B], f: A => C, g: B => D) =>
- laws.alignHomomorphism[A, B, C, D](fa, fb, f, g)
- },
- "alignWith consistent" -> forAll { (fa: F[A], fb: F[B], f: A Ior B => C) =>
- laws.alignWithConsistent[A, B, C](fa, fb, f)
- }
+ new DefaultRuleSet(
+ name = "align",
+ parent = None,
+ "align associativity" -> forAll(laws.alignAssociativity[A, B, C] _),
+ "align homomorphism" -> forAll(laws.alignHomomorphism[A, B, C, D] _),
+ "alignWith consistent" -> forAll(laws.alignWithConsistent[A, B, C] _),
+ "alignMergeWith consistent" -> forAll(laws.alignMergeWithConsistent[A] _)
)
}
diff --git a/laws/src/main/scala/cats/laws/discipline/AlternativeTests.scala b/laws/src/main/scala/cats/laws/discipline/AlternativeTests.scala
index 7fc610ac00..b946896690 100644
--- a/laws/src/main/scala/cats/laws/discipline/AlternativeTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/AlternativeTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -29,7 +50,8 @@ trait AlternativeTests[F[_]] extends NonEmptyAlternativeTests[F] with MonoidKTes
val bases: Seq[(String, RuleSet)] = Nil
val parents: Seq[RuleSet] = Seq(monoidK[A], nonEmptyAlternative[A, B, C])
val props: Seq[(String, Prop)] = Seq(
- "right absorption" -> forAll(laws.alternativeRightAbsorption[A, B] _)
+ "right absorption" -> forAll(laws.alternativeRightAbsorption[A, B] _),
+ "fromIterableOnce" -> forAll(laws.fromIterableOnce[A] _)
)
}
}
diff --git a/laws/src/main/scala/cats/laws/discipline/ApplicativeErrorTests.scala b/laws/src/main/scala/cats/laws/discipline/ApplicativeErrorTests.scala
index b9066b845b..5597fad20a 100644
--- a/laws/src/main/scala/cats/laws/discipline/ApplicativeErrorTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ApplicativeErrorTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -54,6 +75,11 @@ trait ApplicativeErrorTests[F[_], E] extends ApplicativeTests[F] {
"applicativeError attempt fromEither consistent with pure" -> forAll(
laws.attemptFromEitherConsistentWithPure[A] _
),
+ "applicativeError voidError consistent with void+handleError" -> forAll { (a: A) =>
+ // Should be an implicit parameter but that is not a binary-compatible change
+ implicit val eqFUnit: Eq[F[Unit]] = makeEqFUnit[A](a)
+ forAll(laws.voidErrorConsistentWithHandleError _)
+ },
"applicativeError onError pure" -> forAll(laws.onErrorPure[A] _),
"applicativeError onError raise" -> forAll(laws.onErrorRaise[A] _),
"applicativeError adaptError pure" -> forAll(laws.adaptErrorPure[A] _),
diff --git a/laws/src/main/scala/cats/laws/discipline/ApplicativeTests.scala b/laws/src/main/scala/cats/laws/discipline/ApplicativeTests.scala
index 510024fa04..8ac2829ee2 100644
--- a/laws/src/main/scala/cats/laws/discipline/ApplicativeTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ApplicativeTests.scala
@@ -1,14 +1,38 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
import cats.laws.discipline.SemigroupalTests.Isomorphisms
-import org.scalacheck.{Arbitrary, Cogen, Prop}
-import Prop._
+import org.scalacheck.Prop._
+import org.scalacheck.{Arbitrary, Cogen, Gen}
trait ApplicativeTests[F[_]] extends ApplyTests[F] {
def laws: ApplicativeLaws[F]
+ private[discipline] def makeEqFUnit[A](a: A)(implicit EqFA: Eq[F[A]]): Eq[F[Unit]] =
+ Eq.by(fa => laws.F.as(fa, a))
+
def applicative[A: Arbitrary, B: Arbitrary, C: Arbitrary](implicit
ArbFA: Arbitrary[F[A]],
ArbFB: Arbitrary[F[B]],
@@ -23,7 +47,7 @@ trait ApplicativeTests[F[_]] extends ApplyTests[F] {
EqFC: Eq[F[C]],
EqFABC: Eq[F[(A, B, C)]],
iso: Isomorphisms[F]
- ): RuleSet =
+ ): RuleSet = {
new DefaultRuleSet(
name = "applicative",
parent = Some(apply[A, B, C]),
@@ -33,9 +57,15 @@ trait ApplicativeTests[F[_]] extends ApplyTests[F] {
"applicative map" -> forAll(laws.applicativeMap[A, B] _),
"applicative unit" -> forAll(laws.applicativeUnit[A] _),
"ap consistent with product + map" -> forAll(laws.apProductConsistent[A, B] _),
+ "replicateA_ consistent with replicateA.void" -> forAll { (a: A) =>
+ // Should be an implicit parameter but that is not a binary-compatible change
+ implicit val eqFUnit: Eq[F[Unit]] = makeEqFUnit[A](a)
+ forAll(Gen.resize(4, ArbFA.arbitrary))(laws.replicateAVoidReplicateA_Consistent[A](4, _))
+ },
"monoidal left identity" -> forAll((fa: F[A]) => iso.leftIdentity(laws.monoidalLeftIdentity(fa))),
"monoidal right identity" -> forAll((fa: F[A]) => iso.rightIdentity(laws.monoidalRightIdentity(fa)))
)
+ }
}
object ApplicativeTests {
diff --git a/laws/src/main/scala/cats/laws/discipline/ApplyTests.scala b/laws/src/main/scala/cats/laws/discipline/ApplyTests.scala
index 57ba7983ab..861237b070 100644
--- a/laws/src/main/scala/cats/laws/discipline/ApplyTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ApplyTests.scala
@@ -1,10 +1,32 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
import cats.laws.discipline.SemigroupalTests.Isomorphisms
import org.scalacheck.{Arbitrary, Cogen, Prop}
-import Prop._
+import Prop.*
+import org.typelevel.discipline.Laws
trait ApplyTests[F[_]] extends FunctorTests[F] with SemigroupalTests[F] {
def laws: ApplyLaws[F]
@@ -26,7 +48,7 @@ trait ApplyTests[F[_]] extends FunctorTests[F] with SemigroupalTests[F] {
new RuleSet {
val name = "apply"
val parents = Seq(functor[A, B, C], semigroupal[A, B, C])
- val bases = Seq.empty
+ val bases: Seq[(String, Laws#RuleSet)] = Seq.empty
val props = Seq(
"apply composition" -> forAll(laws.applyComposition[A, B, C] _),
"map2/product-map consistency" -> forAll(laws.map2ProductConsistency[A, B, C] _),
diff --git a/laws/src/main/scala/cats/laws/discipline/ArrowChoiceTests.scala b/laws/src/main/scala/cats/laws/discipline/ArrowChoiceTests.scala
index affff0ee76..8d44b51e55 100644
--- a/laws/src/main/scala/cats/laws/discipline/ArrowChoiceTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ArrowChoiceTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/ArrowTests.scala b/laws/src/main/scala/cats/laws/discipline/ArrowTests.scala
index 13332b4622..3fc52c40a0 100644
--- a/laws/src/main/scala/cats/laws/discipline/ArrowTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ArrowTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/BifoldableTests.scala b/laws/src/main/scala/cats/laws/discipline/BifoldableTests.scala
index 2e391109f1..478d0d8936 100644
--- a/laws/src/main/scala/cats/laws/discipline/BifoldableTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/BifoldableTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/BifunctorTests.scala b/laws/src/main/scala/cats/laws/discipline/BifunctorTests.scala
index 7ca82461cf..2ed10fadc5 100644
--- a/laws/src/main/scala/cats/laws/discipline/BifunctorTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/BifunctorTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.laws.discipline
import cats.{Bifunctor, Eq}
diff --git a/laws/src/main/scala/cats/laws/discipline/BimonadTests.scala b/laws/src/main/scala/cats/laws/discipline/BimonadTests.scala
index 7ff7c71619..716f42078d 100644
--- a/laws/src/main/scala/cats/laws/discipline/BimonadTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/BimonadTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/BitraverseTests.scala b/laws/src/main/scala/cats/laws/discipline/BitraverseTests.scala
index 706077f7a9..c233c79ece 100644
--- a/laws/src/main/scala/cats/laws/discipline/BitraverseTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/BitraverseTests.scala
@@ -1,9 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
import org.scalacheck.{Arbitrary, Cogen}
import org.scalacheck.Prop.forAll
+import org.typelevel.discipline.Laws
trait BitraverseTests[F[_, _]] extends BifoldableTests[F] with BifunctorTests[F] {
def laws: BitraverseLaws[F]
@@ -38,7 +60,7 @@ trait BitraverseTests[F[_, _]] extends BifoldableTests[F] with BifunctorTests[F]
new RuleSet {
val name = "bitraverse"
val parents = Seq(bifoldable[A, B, C], bifunctor[A, B, C, D, E, H])
- val bases = Seq.empty
+ val bases: Seq[(String, Laws#RuleSet)] = Seq.empty
val props = Seq(
"bitraverse identity" -> forAll(laws.bitraverseIdentity[A, B] _),
"bitraverse composition" -> forAll(laws.bitraverseCompose[G, A, B, C, D, E, H] _)
diff --git a/laws/src/main/scala/cats/laws/discipline/CategoryTests.scala b/laws/src/main/scala/cats/laws/discipline/CategoryTests.scala
index 038fa7850a..4875bff4ea 100644
--- a/laws/src/main/scala/cats/laws/discipline/CategoryTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/CategoryTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/ChoiceTests.scala b/laws/src/main/scala/cats/laws/discipline/ChoiceTests.scala
index 4db1af1176..4bc9960576 100644
--- a/laws/src/main/scala/cats/laws/discipline/ChoiceTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ChoiceTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/CoflatMapTests.scala b/laws/src/main/scala/cats/laws/discipline/CoflatMapTests.scala
index 14c4cfbe61..1f411e81c1 100644
--- a/laws/src/main/scala/cats/laws/discipline/CoflatMapTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/CoflatMapTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/CommutativeApplicativeTests.scala b/laws/src/main/scala/cats/laws/discipline/CommutativeApplicativeTests.scala
index 483e1701de..3a083aa07f 100644
--- a/laws/src/main/scala/cats/laws/discipline/CommutativeApplicativeTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/CommutativeApplicativeTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/CommutativeApplyTests.scala b/laws/src/main/scala/cats/laws/discipline/CommutativeApplyTests.scala
index 58790dfb7c..80e83823f7 100644
--- a/laws/src/main/scala/cats/laws/discipline/CommutativeApplyTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/CommutativeApplyTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/CommutativeArrowTests.scala b/laws/src/main/scala/cats/laws/discipline/CommutativeArrowTests.scala
index 6a9fb28532..26a68386f4 100644
--- a/laws/src/main/scala/cats/laws/discipline/CommutativeArrowTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/CommutativeArrowTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/CommutativeFlatMapTests.scala b/laws/src/main/scala/cats/laws/discipline/CommutativeFlatMapTests.scala
index f83585153e..f531804f88 100644
--- a/laws/src/main/scala/cats/laws/discipline/CommutativeFlatMapTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/CommutativeFlatMapTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/CommutativeMonadTests.scala b/laws/src/main/scala/cats/laws/discipline/CommutativeMonadTests.scala
index 0407fc107c..3f118e9477 100644
--- a/laws/src/main/scala/cats/laws/discipline/CommutativeMonadTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/CommutativeMonadTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/ComonadTests.scala b/laws/src/main/scala/cats/laws/discipline/ComonadTests.scala
index 342f39fa0b..b07c01b2eb 100644
--- a/laws/src/main/scala/cats/laws/discipline/ComonadTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ComonadTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/ComposeTests.scala b/laws/src/main/scala/cats/laws/discipline/ComposeTests.scala
index ff82550a4a..ce7c46081f 100644
--- a/laws/src/main/scala/cats/laws/discipline/ComposeTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ComposeTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/ContravariantMonoidalTests.scala b/laws/src/main/scala/cats/laws/discipline/ContravariantMonoidalTests.scala
index 171875e1e9..8cdc1fec07 100644
--- a/laws/src/main/scala/cats/laws/discipline/ContravariantMonoidalTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ContravariantMonoidalTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -5,7 +26,8 @@ package discipline
import cats.ContravariantMonoidal
import cats.laws.discipline.SemigroupalTests.Isomorphisms
import org.scalacheck.{Arbitrary, Cogen}
-import org.scalacheck.Prop._
+import org.scalacheck.Prop.*
+import org.typelevel.discipline.Laws
trait ContravariantMonoidalTests[F[_]] extends ContravariantSemigroupalTests[F] {
def laws: ContravariantMonoidalLaws[F]
@@ -26,7 +48,7 @@ trait ContravariantMonoidalTests[F[_]] extends ContravariantSemigroupalTests[F]
new RuleSet {
val name = "contravariantMonoidal"
val parents = Seq(contravariantSemigroupal[A, B, C])
- val bases = Seq.empty
+ val bases: Seq[(String, Laws#RuleSet)] = Seq.empty
val props = Seq(
"contravariantMonoidal right unit" ->
forAll(laws.contravariantMonoidalUnitRight[A] _),
diff --git a/laws/src/main/scala/cats/laws/discipline/ContravariantSemigroupalTests.scala b/laws/src/main/scala/cats/laws/discipline/ContravariantSemigroupalTests.scala
index 47bbdc0df2..9a52d41a15 100644
--- a/laws/src/main/scala/cats/laws/discipline/ContravariantSemigroupalTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ContravariantSemigroupalTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -5,7 +26,8 @@ package discipline
import cats.ContravariantSemigroupal
import cats.laws.discipline.SemigroupalTests.Isomorphisms
import org.scalacheck.{Arbitrary, Cogen}
-import org.scalacheck.Prop._
+import org.scalacheck.Prop.*
+import org.typelevel.discipline.Laws
trait ContravariantSemigroupalTests[F[_]] extends ContravariantTests[F] with SemigroupalTests[F] {
def laws: ContravariantSemigroupalLaws[F]
@@ -26,7 +48,7 @@ trait ContravariantSemigroupalTests[F[_]] extends ContravariantTests[F] with Sem
new RuleSet {
val name = "contravariantSemigroupal"
val parents = Seq(contravariant[A, B, C], semigroupal[A, B, C])
- val bases = Seq.empty
+ val bases: Seq[(String, Laws#RuleSet)] = Seq.empty
val props = Seq(
"contravariantSemigroupal contramap2 delta associates" ->
forAll(laws.contravariantSemigroupalContramap2DiagonalAssociates[A] _)
diff --git a/laws/src/main/scala/cats/laws/discipline/ContravariantTests.scala b/laws/src/main/scala/cats/laws/discipline/ContravariantTests.scala
index cd0d72d643..0688dc5093 100644
--- a/laws/src/main/scala/cats/laws/discipline/ContravariantTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ContravariantTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/DeferTests.scala b/laws/src/main/scala/cats/laws/discipline/DeferTests.scala
index 6fb50fa6b2..9951ffa23f 100644
--- a/laws/src/main/scala/cats/laws/discipline/DeferTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/DeferTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/DistributiveTests.scala b/laws/src/main/scala/cats/laws/discipline/DistributiveTests.scala
index 66546831c6..7e6b5560e7 100644
--- a/laws/src/main/scala/cats/laws/discipline/DistributiveTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/DistributiveTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/Eq.scala b/laws/src/main/scala/cats/laws/discipline/Eq.scala
index 0ddf866bf9..471d82b127 100644
--- a/laws/src/main/scala/cats/laws/discipline/Eq.scala
+++ b/laws/src/main/scala/cats/laws/discipline/Eq.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -14,116 +35,104 @@ import org.scalacheck.Arbitrary
object eq {
implicit def catsLawsEqForFn1Exhaustive[A, B](implicit A: ExhaustiveCheck[A], B: Eq[B]): Eq[A => B] =
- Eq.instance((f, g) => A.allValues.forall(a => B.eqv(f(a), g(a))))
+ (f, g) => A.allValues.forall(a => B.eqv(f(a), g(a)))
implicit def catsLawsEqForFn2[A, B, C](implicit ev: Eq[((A, B)) => C]): Eq[(A, B) => C] =
- Eq.by((_: (A, B) => C).tupled)
+ Eq.by(_.tupled)
implicit def catsLawsEqForPartialFunctionExhaustive[A: ExhaustiveCheck, B: Eq]: Eq[PartialFunction[A, B]] =
- Eq.instance((f, g) =>
+ (f, g) =>
ExhaustiveCheck[A].allValues
.filter(a => f.isDefinedAt(a) || g.isDefinedAt(a))
.forall(a => f.isDefinedAt(a) && g.isDefinedAt(a) && Eq[B].eqv(f(a), g(a)))
- )
implicit def catsLawsEqForAndThen[A, B](implicit eqAB: Eq[A => B]): Eq[AndThen[A, B]] =
- Eq.by[AndThen[A, B], A => B](identity)
+ Eq.by(identity[A => B])
implicit def catsLawsEqForShow[A](implicit ev: Eq[A => String]): Eq[Show[A]] =
- Eq.by[Show[A], A => String](showA => a => showA.show(a))
+ Eq.by(showA => showA.show _)
implicit def catsLawsEqForEq[A](implicit ev: Eq[(A, A) => Boolean]): Eq[Eq[A]] =
- Eq.by[Eq[A], (A, A) => Boolean](e => (a1, a2) => e.eqv(a1, a2))
+ Eq.by(e => e.eqv _)
implicit def catsLawsEqForEquiv[A](implicit ev: Eq[(A, A) => Boolean]): Eq[Equiv[A]] =
- Eq.by[Equiv[A], (A, A) => Boolean](e => (a1, a2) => e.equiv(a1, a2))
+ Eq.by(e => e.equiv _)
implicit def catsLawsEqForPartialOrder[A](implicit ev: Eq[(A, A) => Option[Int]]): Eq[PartialOrder[A]] =
- Eq.by[PartialOrder[A], (A, A) => Option[Int]](o => (a1, a2) => o.tryCompare(a1, a2))
+ Eq.by(o => o.tryCompare _)
- implicit def catsLawsEqForPartialOrdering[A](implicit
- ev: Eq[(A, A) => Option[Int]]
- ): Eq[PartialOrdering[A]] =
- Eq.by[PartialOrdering[A], (A, A) => Option[Int]]((o: PartialOrdering[A]) => (a1, a2) => o.tryCompare(a1, a2))
+ implicit def catsLawsEqForPartialOrdering[A](implicit ev: Eq[(A, A) => Option[Int]]): Eq[PartialOrdering[A]] =
+ Eq.by(o => o.tryCompare _)
implicit def catsLawsEqForOrder[A](implicit ev: Eq[(A, A) => Int]): Eq[Order[A]] =
- Eq.by[Order[A], (A, A) => Int](o => (a1, a2) => o.compare(a1, a2))
+ Eq.by(o => o.compare _)
implicit def catsLawsEqForOrdering[A](implicit ev: Eq[(A, A) => Int]): Eq[Ordering[A]] =
- Eq.by[Ordering[A], (A, A) => Int](o => (a1, a2) => o.compare(a1, a2))
+ Eq.by(o => o.compare _)
implicit def catsLawsEqForHash[A](implicit ev: Eq[A => Int]): Eq[Hash[A]] =
- Eq.by[Hash[A], A => Int](h => a => h.hash(a))
+ Eq.by(h => h.hash _)
implicit def catsLawsEqForSemigroup[A](implicit ev: Eq[(A, A) => A]): Eq[Semigroup[A]] =
- Eq.by[Semigroup[A], (A, A) => A](s => (a1, a2) => s.combine(a1, a2))
+ Eq.by(s => s.combine _)
implicit def catsLawsEqForCommutativeSemigroup[A](implicit
eqA: Eq[A],
ev: Eq[(A, A) => (A, A)]
): Eq[CommutativeSemigroup[A]] =
- Eq.by[CommutativeSemigroup[A], (A, A) => (A, A)](s => (x, y) => (s.combine(x, y), s.combine(y, x)))
+ Eq.by(s => (x: A, y: A) => (s.combine(x, y), s.combine(y, x)))
implicit def catsLawsEqForBand[A](implicit ev: Eq[(A, A) => (A, A)]): Eq[Band[A]] =
- Eq.by[Band[A], (A, A) => (A, A)](f => (x, y) => (f.combine(x, y), f.combine(f.combine(x, y), y)))
+ Eq.by(f => (x: A, y: A) => (f.combine(x, y), f.combine(f.combine(x, y), y)))
implicit def catsLawsEqForGroup[A](implicit ev1: Eq[(A, A) => (A, Boolean)], eqA: Eq[A]): Eq[Group[A]] =
- Eq.by[Group[A], (A, A) => (A, Boolean)] {
- f =>
- { (x, y) =>
- {
- val xy = f.combine(x, y)
- val p1 = f.combine(f.inverse(x), x) === f.empty && f.combine(x, f.inverse(x)) === f.empty
- val p2 = f.combine(f.inverse(y), y) === f.empty && f.combine(y, f.inverse(y)) === f.empty
- val p3 = f.inverse(f.empty) == f.empty
-
- (xy, p1 && p2 && p3)
- }
- }
- }
+ Eq.by(f => { (x: A, y: A) =>
+ val xy = f.combine(x, y)
+ val p1 = f.combine(f.inverse(x), x) === f.empty && f.combine(x, f.inverse(x)) === f.empty
+ val p2 = f.combine(f.inverse(y), y) === f.empty && f.combine(y, f.inverse(y)) === f.empty
+ val p3 = f.inverse(f.empty) == f.empty
+ (xy, p1 && p2 && p3)
+ })
implicit def catsLawsEqForMonoid[A](implicit eqSA: Eq[Semigroup[A]], eqA: Eq[A]): Eq[Monoid[A]] =
- new Eq[Monoid[A]] {
- def eqv(f: Monoid[A], g: Monoid[A]): Boolean =
- eqSA.eqv(f, g) && eqA.eqv(f.empty, g.empty)
- }
+ (f, g) => eqSA.eqv(f, g) && eqA.eqv(f.empty, g.empty)
implicit def catsLawsEqForSemilattice[A](implicit
eqBA: Eq[Band[A]],
eqCA: Eq[CommutativeSemigroup[A]],
eqA: Eq[A]
): Eq[Semilattice[A]] =
- Eq.instance((f, g) => eqBA.eqv(f, g) && eqCA.eqv(f, g))
+ (f, g) => eqBA.eqv(f, g) && eqCA.eqv(f, g)
implicit def catsLawsEqForCommutativeMonoid[A](implicit
eqSA: Eq[CommutativeSemigroup[A]],
eqMA: Eq[Monoid[A]],
eqA: Eq[A]
): Eq[CommutativeMonoid[A]] =
- Eq.instance((f, g) => eqSA.eqv(f, g) && eqMA.eqv(f, g))
+ (f, g) => eqSA.eqv(f, g) && eqMA.eqv(f, g)
implicit def catsLawsEqForBoundedSemilattice[A](implicit
eqSA: Eq[Semilattice[A]],
eqCA: Eq[CommutativeMonoid[A]],
eqA: Eq[A]
): Eq[BoundedSemilattice[A]] =
- Eq.instance((f, g) => eqSA.eqv(f, g) && eqCA.eqv(f, g))
+ (f, g) => eqSA.eqv(f, g) && eqCA.eqv(f, g)
implicit def catsLawsEqForCommutativeGroup[A](implicit
eqMA: Eq[CommutativeMonoid[A]],
eqGA: Eq[Group[A]],
eqA: Eq[A]
): Eq[CommutativeGroup[A]] =
- Eq.instance((f, g) => eqMA.eqv(f, g) && eqGA.eqv(f, g))
+ (f, g) => eqMA.eqv(f, g) && eqGA.eqv(f, g)
implicit def catsLawsEqForRepresentableStore[F[_]: Representable, S, A](implicit
eqFA: Eq[F[A]],
eqS: Eq[S]
): Eq[RepresentableStore[F, S, A]] =
- Eq.instance((s1, s2) => eqFA.eqv(s1.fa, s2.fa) && eqS.eqv(s1.index, s2.index))
+ (s1, s2) => eqFA.eqv(s1.fa, s2.fa) && eqS.eqv(s1.index, s2.index)
implicit def catsLawsEqForStoreT[F[_], S, A](implicit eqF: Eq[F[S => A]], eqS: Eq[S]): Eq[StoreT[F, S, A]] =
- Eq.instance((s1, s2) => eqF.eqv(s1.runF, s2.runF) && eqS.eqv(s1.index, s2.index))
+ (s1, s2) => eqF.eqv(s1.runF, s2.runF) && eqS.eqv(s1.index, s2.index)
}
@deprecated(
@@ -139,56 +148,47 @@ object eq {
"This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForFn1Exhaustive instead. See https://github.com/typelevel/cats/pull/2577 for more information.",
"1.7"
)
- implicit def catsLawsEqForFn1[A, B](implicit A: Arbitrary[A], B: Eq[B]): Eq[A => B] =
- new Eq[A => B] {
- val sampleCnt: Int = if (Platform.isJvm) 50 else 30
-
- def eqv(f: A => B, g: A => B): Boolean = {
- val samples = List.fill(sampleCnt)(A.arbitrary.sample).collect {
- case Some(a) => a
- case None => sys.error("Could not generate arbitrary values to compare two functions")
- }
- samples.forall(s => B.eqv(f(s), g(s)))
- }
+ implicit def catsLawsEqForFn1[A, B](implicit A: Arbitrary[A], B: Eq[B]): Eq[A => B] = { (f, g) =>
+ val sampleCnt = if (Platform.isJvm) 50 else 30
+ val samples = List.fill(sampleCnt)(A.arbitrary.sample).collect {
+ case Some(a) => a
+ case None => sys.error("Could not generate arbitrary values to compare two functions")
}
+ samples.forall(s => B.eqv(f(s), g(s)))
+ }
/**
* Create an approximation of Eq[(A, B) => C] by generating random values for A and B
* and comparing the application of the two functions.
*/
implicit def catsLawsEqForFn2[A, B, C](implicit A: Arbitrary[A], B: Arbitrary[B], C: Eq[C]): Eq[(A, B) => C] =
- Eq.by((_: (A, B) => C).tupled)(catsLawsEqForFn1[(A, B), C])
+ Eq.by(_.tupled)
/**
* `Eq[AndThen]` instance, built by piggybacking on [[catsLawsEqForFn1]].
*/
implicit def catsLawsEqForAndThen[A, B](implicit A: Arbitrary[A], B: Eq[B]): Eq[AndThen[A, B]] =
- Eq.instance(catsLawsEqForFn1[A, B].eqv(_, _))
+ Eq.by(identity[A => B])
/**
- * Create an approximation of Eq[Show[A]] by using catsLawsEqForFn1[A, String]
+ * Create an approximation of `Eq[Show[A]]` by using catsLawsEqForFn1[A, String]
*/
implicit def catsLawsEqForShow[A: Arbitrary]: Eq[Show[A]] =
- Eq.by[Show[A], A => String] { showInstance => (a: A) =>
- showInstance.show(a)
- }(catsLawsEqForFn1)
+ Eq.by(showA => showA.show _)
/**
* Create an approximate Eq instance for some type A, by comparing
* the behavior of `f(x, b)` and `f(y, b)` across many `b` samples.
*/
- def sampledEq[A, B: Arbitrary, C: Eq](samples: Int)(f: (A, B) => C): Eq[A] =
- new Eq[A] {
- val gen = Arbitrary.arbitrary[B]
- def eqv(x: A, y: A): Boolean =
- Iterator
- .range(1, samples)
- .map(_ => gen.sample)
- .map(_.getOrElse(sys.error(s"generator $gen failed")))
- .forall { b =>
- f(x, b) === f(y, b)
- }
- }
+ def sampledEq[A, B: Arbitrary, C: Eq](samples: Int)(f: (A, B) => C): Eq[A] = {
+ val gen = Arbitrary.arbitrary[B]
+ (x, y) =>
+ Iterator
+ .range(1, samples)
+ .map(_ => gen.sample)
+ .map(_.getOrElse(sys.error(s"generator $gen failed")))
+ .forall(b => f(x, b) === f(y, b))
+ }
implicit def catsLawsEqForEq[A](implicit arbA: Arbitrary[(A, A)]): Eq[Eq[A]] =
sampledEq[Eq[A], (A, A), Boolean](100) { case (e, (l, r)) => e.eqv(l, r) }
@@ -215,42 +215,35 @@ object eq {
sampledEq[Ordering[A], (A, A), Int](100) { case (p, (l, r)) => p.compare(l, r) }
/**
- * Creates an approximation of Eq[Hash[A]] by generating 100 values for A
+ * Creates an approximation of `Eq[Hash[A]]` by generating 100 values for A
* and comparing the application of the two hash functions.
*/
- implicit def catsLawsEqForHash[A](implicit arbA: Arbitrary[A]): Eq[Hash[A]] =
- new Eq[Hash[A]] {
- def eqv(f: Hash[A], g: Hash[A]): Boolean = {
- val samples = List.fill(100)(arbA.arbitrary.sample).collect {
- case Some(a) => a
- case None => sys.error("Could not generate arbitrary values to compare two Hash[A]")
- }
- samples.forall { x =>
- f.hash(x) == g.hash(x)
- }
- }
+ implicit def catsLawsEqForHash[A](implicit arbA: Arbitrary[A]): Eq[Hash[A]] = { (f, g) =>
+ val samples = List.fill(100)(arbA.arbitrary.sample).collect {
+ case Some(a) => a
+ case None => sys.error("Could not generate arbitrary values to compare two Hash[A]")
}
+ samples.forall(x => f.hash(x) == g.hash(x))
+ }
/**
- * Create an approximation of Eq[Semigroup[A]] by generating values for A
+ * Create an approximation of `Eq[Semigroup[A]]` by generating values for A
* and comparing the application of the two combine functions.
*/
- implicit def catsLawsEqForSemigroup[A](implicit arbAA: Arbitrary[(A, A)], eqA: Eq[A]): Eq[Semigroup[A]] = {
- val instance: Eq[((A, A)) => A] = catsLawsEqForFn1[(A, A), A]
- Eq.by[Semigroup[A], ((A, A)) => A](f => Function.tupled((x, y) => f.combine(x, y)))(instance)
- }
+ implicit def catsLawsEqForSemigroup[A](implicit arbAA: Arbitrary[(A, A)], eqA: Eq[A]): Eq[Semigroup[A]] =
+ Eq.by[Semigroup[A], ((A, A)) => A](f => { case (x, y) => f.combine(x, y) })
implicit def catsLawsEqForCommutativeSemigroup[A](implicit
arbAA: Arbitrary[(A, A)],
eqA: Eq[A]
): Eq[CommutativeSemigroup[A]] = {
- implicit val eqABool: Eq[(A, Boolean)] = Eq.instance { case ((x, boolX), (y, boolY)) =>
+ implicit val eqABool: Eq[(A, Boolean)] = { case ((x, boolX), (y, boolY)) =>
x === y && boolX === boolY
}
- Eq.by[CommutativeSemigroup[A], ((A, A)) => (A, Boolean)](f =>
- Function.tupled((x, y) => (f.combine(x, y), f.combine(x, y) === f.combine(y, x)))
- )(catsLawsEqForFn1[(A, A), (A, Boolean)])
+ Eq.by[CommutativeSemigroup[A], ((A, A)) => (A, Boolean)](f => { case (x, y) =>
+ (f.combine(x, y), f.combine(x, y) === f.combine(y, x))
+ })
}
implicit def catsLawsEqForBand[A](implicit
@@ -258,30 +251,27 @@ object eq {
eqSA: Eq[Semigroup[A]],
eqA: Eq[A]
): Eq[Band[A]] =
- Eq.by[Band[A], ((A, A)) => Boolean](f =>
- Function.tupled((x, y) => f.combine(x, y) === f.combine(f.combine(x, y), y))
- )(catsLawsEqForFn1[(A, A), Boolean])
+ Eq.by[Band[A], ((A, A)) => Boolean](f => { case (x, y) =>
+ f.combine(x, y) === f.combine(f.combine(x, y), y)
+ })
implicit def catsLawsEqForGroup[A](implicit
arbAA: Arbitrary[(A, A)],
eqMA: Eq[Monoid[A]],
eqA: Eq[A]
): Eq[Group[A]] = {
- implicit val eqABool: Eq[(A, Boolean)] = Eq.instance { case ((x, boolX), (y, boolY)) =>
+ implicit val eqABool: Eq[(A, Boolean)] = { case ((x, boolX), (y, boolY)) =>
x === y && boolX === boolY
}
- val inverseEq = Eq.by[Group[A], ((A, A)) => (A, Boolean)](f =>
- Function.tupled { (x, y) =>
- val xy = f.combine(x, y)
- val p1 = f.combine(f.inverse(x), x) === f.empty && f.combine(x, f.inverse(x)) === f.empty
- val p2 = f.combine(f.inverse(y), y) === f.empty && f.combine(y, f.inverse(y)) === f.empty
- val p3 = f.inverse(f.empty) == f.empty
-
- (xy, p1 && p2 && p3)
- }
- )(catsLawsEqForFn1[(A, A), (A, Boolean)])
+ val inverseEq = Eq.by[Group[A], ((A, A)) => (A, Boolean)](f => { case (x, y) =>
+ val xy = f.combine(x, y)
+ val p1 = f.combine(f.inverse(x), x) === f.empty && f.combine(x, f.inverse(x)) === f.empty
+ val p2 = f.combine(f.inverse(y), y) === f.empty && f.combine(y, f.inverse(y)) === f.empty
+ val p3 = f.inverse(f.empty) == f.empty
+ (xy, p1 && p2 && p3)
+ })
- Eq.instance((f, g) => eqMA.eqv(f, g) && inverseEq.eqv(f, g))
+ (f, g) => eqMA.eqv(f, g) && inverseEq.eqv(f, g)
}
}
diff --git a/laws/src/main/scala/cats/laws/discipline/ExhaustiveCheck.scala b/laws/src/main/scala/cats/laws/discipline/ExhaustiveCheck.scala
index 3db53269c5..3ec2d4f7dd 100644
--- a/laws/src/main/scala/cats/laws/discipline/ExhaustiveCheck.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ExhaustiveCheck.scala
@@ -1,10 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
/**
* An `ExhuastiveCheck[A]` instance can be used similarly to a ScalaCheck
- * `Gen[A]` instance, but differs in that it generates a `Stream` of the entire
+ * `Gen[A]` instance, but differs in that it generates a `List` of the entire
* domain of values as opposed to generating a random sampling of values.
*/
trait ExhaustiveCheck[A] extends Serializable { self =>
diff --git a/laws/src/main/scala/cats/laws/discipline/FlatMapTests.scala b/laws/src/main/scala/cats/laws/discipline/FlatMapTests.scala
index 4a91d99fc6..c048b118c4 100644
--- a/laws/src/main/scala/cats/laws/discipline/FlatMapTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/FlatMapTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/FoldableTests.scala b/laws/src/main/scala/cats/laws/discipline/FoldableTests.scala
index 6082ecd95a..3027591b27 100644
--- a/laws/src/main/scala/cats/laws/discipline/FoldableTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/FoldableTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/FunctorFilterTests.scala b/laws/src/main/scala/cats/laws/discipline/FunctorFilterTests.scala
index be33e0be87..f3898c6350 100644
--- a/laws/src/main/scala/cats/laws/discipline/FunctorFilterTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/FunctorFilterTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/FunctorTests.scala b/laws/src/main/scala/cats/laws/discipline/FunctorTests.scala
index c751475eaa..47eab16b27 100644
--- a/laws/src/main/scala/cats/laws/discipline/FunctorTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/FunctorTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -20,7 +41,8 @@ trait FunctorTests[F[_]] extends InvariantTests[F] {
name = "functor",
parent = Some(invariant[A, B, C]),
"covariant identity" -> forAll(laws.covariantIdentity[A] _),
- "covariant composition" -> forAll(laws.covariantComposition[A, B, C] _)
+ "covariant composition" -> forAll(laws.covariantComposition[A, B, C] _),
+ "mapOrKeepToMapEquivalence" -> forAll(laws.mapOrKeepToMapEquivalence[A, A] _)
)
}
diff --git a/laws/src/main/scala/cats/laws/discipline/InjectKTests.scala b/laws/src/main/scala/cats/laws/discipline/InjectKTests.scala
index a6eed7fe61..27046fbb0c 100644
--- a/laws/src/main/scala/cats/laws/discipline/InjectKTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/InjectKTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/InjectTests.scala b/laws/src/main/scala/cats/laws/discipline/InjectTests.scala
index 8619d84cb9..14427cfffd 100644
--- a/laws/src/main/scala/cats/laws/discipline/InjectTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/InjectTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala b/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala
index fda5324eec..3920261a11 100644
--- a/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala
@@ -1,10 +1,32 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
import cats.laws.discipline.SemigroupalTests.Isomorphisms
import org.scalacheck.{Arbitrary, Cogen}
-import org.scalacheck.Prop._
+import org.scalacheck.Prop.*
+import org.typelevel.discipline.Laws
trait InvariantMonoidalTests[F[_]] extends InvariantSemigroupalTests[F] {
def laws: InvariantMonoidalLaws[F]
@@ -26,7 +48,7 @@ trait InvariantMonoidalTests[F[_]] extends InvariantSemigroupalTests[F] {
new RuleSet {
val name = "invariantMonoidal"
val parents = Seq(invariantSemigroupal[A, B, C])
- val bases = Seq.empty
+ val bases: Seq[(String, Laws#RuleSet)] = Seq.empty
val props = Seq(
"invariant monoidal left identity" -> forAll((fa: F[A]) => laws.invariantMonoidalLeftIdentity(fa)),
"invariant monoidal right identity" -> forAll((fa: F[A]) => laws.invariantMonoidalRightIdentity(fa))
diff --git a/laws/src/main/scala/cats/laws/discipline/InvariantSemigroupalTests.scala b/laws/src/main/scala/cats/laws/discipline/InvariantSemigroupalTests.scala
index 4717d27bd1..6f13cf7695 100644
--- a/laws/src/main/scala/cats/laws/discipline/InvariantSemigroupalTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/InvariantSemigroupalTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -5,6 +26,7 @@ package discipline
import cats.laws.discipline.SemigroupalTests.Isomorphisms
import org.scalacheck.Prop.forAll
import org.scalacheck.{Arbitrary, Cogen}
+import org.typelevel.discipline.Laws
trait InvariantSemigroupalTests[F[_]] extends InvariantTests[F] with SemigroupalTests[F] {
def laws: InvariantSemigroupalLaws[F]
@@ -26,7 +48,7 @@ trait InvariantSemigroupalTests[F[_]] extends InvariantTests[F] with Semigroupal
new RuleSet {
val name = "invariantSemigroupal"
val parents = Seq(invariant[A, B, C], semigroupal[A, B, C])
- val bases = Nil
+ val bases: Seq[(String, Laws#RuleSet)] = Nil
val props = Seq(
"invariant semigroupal associativity" -> forAll((fa: F[A], fb: F[B], fc: F[C]) =>
laws.invariantSemigroupalAssociativity(fa, fb, fc)
diff --git a/laws/src/main/scala/cats/laws/discipline/InvariantTests.scala b/laws/src/main/scala/cats/laws/discipline/InvariantTests.scala
index 14dbc2441a..8634d0f1b7 100644
--- a/laws/src/main/scala/cats/laws/discipline/InvariantTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/InvariantTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/MiniInt.scala b/laws/src/main/scala/cats/laws/discipline/MiniInt.scala
index 2958124c70..ffd877221e 100644
--- a/laws/src/main/scala/cats/laws/discipline/MiniInt.scala
+++ b/laws/src/main/scala/cats/laws/discipline/MiniInt.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -51,7 +72,7 @@ object MiniInt {
val allValues: List[MiniInt] = (minIntValue to maxIntValue).map(unsafeFromInt).toList
- implicit val catsLawsEqInstancesForMiniInt: Order[MiniInt] with Hash[MiniInt] =
+ implicit val catsLawsEqInstancesForMiniInt: Order[MiniInt] & Hash[MiniInt] =
new Order[MiniInt] with Hash[MiniInt] {
def hash(x: MiniInt): Int = Hash[Int].hash(x.intBits)
diff --git a/laws/src/main/scala/cats/laws/discipline/MonadErrorTests.scala b/laws/src/main/scala/cats/laws/discipline/MonadErrorTests.scala
index 8673fb7b1b..f1d839aed9 100644
--- a/laws/src/main/scala/cats/laws/discipline/MonadErrorTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/MonadErrorTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/MonadTests.scala b/laws/src/main/scala/cats/laws/discipline/MonadTests.scala
index 82459d34d6..0bb727bd0d 100644
--- a/laws/src/main/scala/cats/laws/discipline/MonadTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/MonadTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -34,7 +55,8 @@ trait MonadTests[F[_]] extends ApplicativeTests[F] with FlatMapTests[F] {
Seq(
"monad left identity" -> forAll(laws.monadLeftIdentity[A, B] _),
"monad right identity" -> forAll(laws.monadRightIdentity[A] _),
- "map flatMap coherence" -> forAll(laws.mapFlatMapCoherence[A, B] _)
+ "map flatMap coherence" -> forAll(laws.mapFlatMapCoherence[A, B] _),
+ "flatMapOrKeep flatMap coherence" -> forAll(laws.flatMapOrKeepToFlatMapCoherence[A, A] _)
) ++ (if (Platform.isJvm) Seq[(String, Prop)]("tailRecM stack safety" -> Prop.lzy(laws.tailRecMStackSafety))
else Seq.empty)
}
@@ -63,7 +85,8 @@ trait MonadTests[F[_]] extends ApplicativeTests[F] with FlatMapTests[F] {
Seq(
"monad left identity" -> forAll(laws.monadLeftIdentity[A, B] _),
"monad right identity" -> forAll(laws.monadRightIdentity[A] _),
- "map flatMap coherence" -> forAll(laws.mapFlatMapCoherence[A, B] _)
+ "map flatMap coherence" -> forAll(laws.mapFlatMapCoherence[A, B] _),
+ "flatMapOrKeep flatMap coherence" -> forAll(laws.flatMapOrKeepToFlatMapCoherence[A, A] _)
)
}
}
diff --git a/laws/src/main/scala/cats/laws/discipline/MonoidKTests.scala b/laws/src/main/scala/cats/laws/discipline/MonoidKTests.scala
index f1465a3e1a..17f2ca9be7 100644
--- a/laws/src/main/scala/cats/laws/discipline/MonoidKTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/MonoidKTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/NonEmptyAlternativeTests.scala b/laws/src/main/scala/cats/laws/discipline/NonEmptyAlternativeTests.scala
index 32782057ac..e72aab5fe0 100644
--- a/laws/src/main/scala/cats/laws/discipline/NonEmptyAlternativeTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/NonEmptyAlternativeTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/NonEmptyParallelTests.scala b/laws/src/main/scala/cats/laws/discipline/NonEmptyParallelTests.scala
index ef92f5e834..2729b5aa4e 100644
--- a/laws/src/main/scala/cats/laws/discipline/NonEmptyParallelTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/NonEmptyParallelTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/NonEmptyTraverseTests.scala b/laws/src/main/scala/cats/laws/discipline/NonEmptyTraverseTests.scala
index 011c3ae97a..6df6cc7877 100644
--- a/laws/src/main/scala/cats/laws/discipline/NonEmptyTraverseTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/NonEmptyTraverseTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.laws.discipline
import org.scalacheck.{Arbitrary, Cogen, Prop}
@@ -9,7 +30,15 @@ import cats.laws.NonEmptyTraverseLaws
trait NonEmptyTraverseTests[F[_]] extends TraverseTests[F] with ReducibleTests[F] {
def laws: NonEmptyTraverseLaws[F]
- def nonEmptyTraverse[G[_]: Applicative, A: Arbitrary, B: Arbitrary, C: Arbitrary, M: Arbitrary, X[_], Y[_]](implicit
+ def nonEmptyTraverse[
+ G[_]: Applicative,
+ A: Arbitrary,
+ B: Arbitrary,
+ C: Arbitrary,
+ M: Arbitrary,
+ X[_],
+ Y[_]
+ ](implicit
ArbFA: Arbitrary[F[A]],
ArbXB: Arbitrary[X[B]],
ArbYB: Arbitrary[Y[B]],
@@ -43,26 +72,19 @@ trait NonEmptyTraverseTests[F[_]] extends TraverseTests[F] with ReducibleTests[F
EqYFB: Eq[Y[F[B]]],
EqYFM: Eq[Y[F[M]]],
EqOptionA: Eq[Option[A]]
- ): RuleSet = {
- implicit def EqXFBYFB: Eq[(X[F[B]], Y[F[B]])] =
- new Eq[(X[F[B]], Y[F[B]])] {
- override def eqv(x: (X[F[B]], Y[F[B]]), y: (X[F[B]], Y[F[B]])): Boolean =
- EqXFB.eqv(x._1, y._1) && EqYFB.eqv(x._2, y._2)
- }
- new RuleSet {
- def name: String = "nonEmptyTraverse"
- def bases: Seq[(String, RuleSet)] = Nil
- def parents: Seq[RuleSet] = Seq(traverse[A, B, C, M, X, Y], reducible[G, A, B])
- def props: Seq[(String, Prop)] =
- Seq(
- "nonEmptyTraverse identity" -> forAll(laws.nonEmptyTraverseIdentity[A, C] _),
- "nonEmptyTraverse sequential composition" -> forAll(
- laws.nonEmptyTraverseSequentialComposition[A, B, C, X, Y] _
- ),
- "nonEmptyTraverse parallel composition" -> forAll(laws.nonEmptyTraverseParallelComposition[A, B, X, Y] _),
- "nonEmptyTraverse derive reduceMap" -> forAll(laws.reduceMapDerived[A, M] _)
- )
- }
+ ): RuleSet = new RuleSet {
+ def name: String = "nonEmptyTraverse"
+ def bases: Seq[(String, RuleSet)] = Nil
+ def parents: Seq[RuleSet] = Seq(traverse[A, B, C, M, X, Y], reducible[G, A, B])
+ def props: Seq[(String, Prop)] =
+ Seq(
+ "nonEmptyTraverse identity" -> forAll(laws.nonEmptyTraverseIdentity[A, C] _),
+ "nonEmptyTraverse sequential composition" -> forAll(
+ laws.nonEmptyTraverseSequentialComposition[A, B, C, X, Y] _
+ ),
+ "nonEmptyTraverse parallel composition" -> forAll(laws.nonEmptyTraverseParallelComposition[A, B, X, Y] _),
+ "nonEmptyTraverse derive reduceMap" -> forAll(laws.reduceMapDerived[A, M] _)
+ )
}
}
diff --git a/laws/src/main/scala/cats/laws/discipline/ParallelTests.scala b/laws/src/main/scala/cats/laws/discipline/ParallelTests.scala
index 93fcb7dfa4..e29fd1a531 100644
--- a/laws/src/main/scala/cats/laws/discipline/ParallelTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ParallelTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/ProfunctorTests.scala b/laws/src/main/scala/cats/laws/discipline/ProfunctorTests.scala
index 3e41109098..66fec28ce7 100644
--- a/laws/src/main/scala/cats/laws/discipline/ProfunctorTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ProfunctorTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/ReducibleTests.scala b/laws/src/main/scala/cats/laws/discipline/ReducibleTests.scala
index 3ad7696241..b0a66a7f04 100644
--- a/laws/src/main/scala/cats/laws/discipline/ReducibleTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ReducibleTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -37,8 +58,8 @@ trait ReducibleTests[F[_]] extends FoldableTests[F] {
forAll(laws.reduceRightConsistentWithReduceRightOption[A] _),
"reduce consistent with reduceLeft" ->
forAll(laws.reduceReduceLeftConsistent[B] _),
- "nonEmptyTraverse_ consistent with traverse_" -> forAll(laws.traverseConsistent[G, A, B] _),
- "nonEmptySequence_ consistent with sequence_" -> forAll(laws.sequenceConsistent[G, A] _),
+ "nonEmptyTraverseVoid consistent with traverseVoid" -> forAll(laws.traverseConsistent[G, A, B] _),
+ "nonEmptySequenceVoid consistent with sequenceVoid" -> forAll(laws.sequenceConsistent[G, A] _),
"size consistent with reduceMap" -> forAll(laws.sizeConsistent[A] _)
)
}
diff --git a/laws/src/main/scala/cats/laws/discipline/RepresentableTests.scala b/laws/src/main/scala/cats/laws/discipline/RepresentableTests.scala
index 22e290682e..4e5441e256 100644
--- a/laws/src/main/scala/cats/laws/discipline/RepresentableTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/RepresentableTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.laws.discipline
import cats.{Eq, Representable}
diff --git a/laws/src/main/scala/cats/laws/discipline/SemigroupKTests.scala b/laws/src/main/scala/cats/laws/discipline/SemigroupKTests.scala
index 11964342c3..f68bd2d426 100644
--- a/laws/src/main/scala/cats/laws/discipline/SemigroupKTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/SemigroupKTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/SemigroupalTests.scala b/laws/src/main/scala/cats/laws/discipline/SemigroupalTests.scala
index 2eeae04eb1..94400317de 100644
--- a/laws/src/main/scala/cats/laws/discipline/SemigroupalTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/SemigroupalTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/ShortCircuitingTests.scala b/laws/src/main/scala/cats/laws/discipline/ShortCircuitingTests.scala
index 91234710ea..f9a79baae0 100644
--- a/laws/src/main/scala/cats/laws/discipline/ShortCircuitingTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/ShortCircuitingTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.laws.discipline
import cats.laws.ShortCircuitingLaws
diff --git a/laws/src/main/scala/cats/laws/discipline/StrongTests.scala b/laws/src/main/scala/cats/laws/discipline/StrongTests.scala
index 963578e77e..661845f556 100644
--- a/laws/src/main/scala/cats/laws/discipline/StrongTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/StrongTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/laws/src/main/scala/cats/laws/discipline/TraverseFilterTests.scala b/laws/src/main/scala/cats/laws/discipline/TraverseFilterTests.scala
index ce75f2cee7..d24d3d81ba 100644
--- a/laws/src/main/scala/cats/laws/discipline/TraverseFilterTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/TraverseFilterTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -27,7 +48,17 @@ trait TraverseFilterTests[F[_]] extends FunctorFilterTests[F] {
EqFC: Eq[F[C]],
EqGFA: Eq[Option[F[A]]],
EqMNFC: Eq[Nested[Option, Option, F[C]]]
- ): RuleSet =
+ ): RuleSet = {
+ implicit val arbFAOB: Arbitrary[PartialFunction[A, Option[B]]] =
+ Arbitrary(ArbFABoo.arbitrary.map { pfab =>
+ {
+ case a if pfab.isDefinedAt(a) =>
+ val b = pfab(a)
+ if (((a.hashCode ^ b.hashCode) & 1) == 1) Some(b)
+ else None
+ }
+ })
+
new DefaultRuleSet(
name = "traverseFilter",
parent = Some(functorFilter[A, B, C]),
@@ -37,8 +68,10 @@ trait TraverseFilterTests[F[_]] extends FunctorFilterTests[F] {
"filterA consistent with traverseFilter" -> forAll(laws.filterAConsistentWithTraverseFilter[Option, A] _),
"traverseEither consistent with traverseFilter" -> forAll(
laws.traverseEitherConsistentWithTraverseFilter[Option, F[A], A, B] _
- )
+ ),
+ "traverseCollect reference" -> forAll(laws.traverseCollectRef[Option, A, B] _)
)
+ }
}
object TraverseFilterTests {
diff --git a/laws/src/main/scala/cats/laws/discipline/TraverseTests.scala b/laws/src/main/scala/cats/laws/discipline/TraverseTests.scala
index cfb3d19db3..5063d2dcac 100644
--- a/laws/src/main/scala/cats/laws/discipline/TraverseTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/TraverseTests.scala
@@ -1,18 +1,44 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
import cats.instances.option._
import cats.kernel.CommutativeMonoid
+import org.scalacheck.Prop._
import org.scalacheck.{Arbitrary, Cogen, Prop}
-import Prop._
trait TraverseTests[F[_]] extends FunctorTests[F] with FoldableTests[F] with UnorderedTraverseTests[F] {
def laws: TraverseLaws[F]
- def traverse[A: Arbitrary, B: Arbitrary, C: Arbitrary, M: Arbitrary, X[_]: CommutativeApplicative, Y[
- _
- ]: CommutativeApplicative](implicit
+ def traverse[
+ A: Arbitrary,
+ B: Arbitrary,
+ C: Arbitrary,
+ M: Arbitrary,
+ X[_]: CommutativeApplicative,
+ Y[_]: CommutativeApplicative
+ ](implicit
ArbFA: Arbitrary[F[A]],
ArbFB: Arbitrary[F[B]],
ArbXB: Arbitrary[X[B]],
@@ -37,29 +63,27 @@ trait TraverseTests[F[_]] extends FunctorTests[F] with FoldableTests[F] with Uno
EqXFM: Eq[X[F[M]]],
EqYFM: Eq[Y[F[M]]],
EqOptionA: Eq[Option[A]]
- ): RuleSet = {
- implicit def EqXFBYFB: Eq[(X[F[B]], Y[F[B]])] =
- new Eq[(X[F[B]], Y[F[B]])] {
- override def eqv(x: (X[F[B]], Y[F[B]]), y: (X[F[B]], Y[F[B]])): Boolean =
- EqXFB.eqv(x._1, y._1) && EqYFB.eqv(x._2, y._2)
- }
- new RuleSet {
- def name: String = "traverse"
- def bases: Seq[(String, RuleSet)] = Nil
- def parents: Seq[RuleSet] = Seq(functor[A, B, C], foldable[A, M], unorderedTraverse[A, M, C, X, Y])
- def props: Seq[(String, Prop)] =
- Seq(
- "traverse identity" -> forAll(laws.traverseIdentity[A, C] _),
- "traverse sequential composition" -> forAll(laws.traverseSequentialComposition[A, B, C, X, Y] _),
- "traverse parallel composition" -> forAll(laws.traverseParallelComposition[A, B, X, Y] _),
- "traverse traverseTap" -> forAll(laws.traverseTap[B, M, X] _),
- "traverse derive foldMap" -> forAll(laws.foldMapDerived[A, M] _),
- "traverse order consistency" -> forAll(laws.traverseOrderConsistent[A] _),
- "traverse ref mapWithIndex" -> forAll(laws.mapWithIndexRef[A, C] _),
- "traverse ref traverseWithIndexM" -> forAll(laws.traverseWithIndexMRef[Option, A, C] _),
- "traverse ref zipWithIndex" -> forAll(laws.zipWithIndexRef[A, C] _)
- )
- }
+ ): RuleSet = new RuleSet {
+ def name: String = "traverse"
+ def bases: Seq[(String, RuleSet)] = Nil
+ def parents: Seq[RuleSet] = Seq(functor[A, B, C], foldable[A, M], unorderedTraverse[A, M, C, X, Y])
+ def props: Seq[(String, Prop)] =
+ Seq(
+ "traverse identity" -> forAll(laws.traverseIdentity[A, C] _),
+ "traverse sequential composition" -> forAll(laws.traverseSequentialComposition[A, B, C, X, Y] _),
+ "traverse parallel composition" -> forAll(laws.traverseParallelComposition[A, B, X, Y] _),
+ "traverse traverseTap" -> forAll(laws.traverseTap[B, M, X] _),
+ "traverse derive foldMap" -> forAll(laws.foldMapDerived[A, M] _),
+ "traverse order consistency" -> forAll(laws.traverseOrderConsistent[A] _),
+ "traverse ref mapAccumulate" -> forAll(laws.mapAccumulateRef[M, A, C] _),
+ "traverse ref mapWithIndex" -> forAll(laws.mapWithIndexRef[A, C] _),
+ "traverse ref traverseWithIndexM" -> forAll(laws.traverseWithIndexMRef[Option, A, C] _),
+ "traverse ref zipWithIndex" -> forAll(laws.zipWithIndexRef[A, C] _),
+ "traverse ref zipWithLongIndex" -> forAll(laws.zipWithLongIndexRef[A, C] _),
+ "traverse ref mapWithLongIndex" -> forAll(laws.mapWithLongIndexRef[A, C] _),
+ "traverse ref traverseWithLongIndexM" -> forAll(laws.traverseWithLongIndexMRef[Option, A, C] _),
+ "traverse ref updated" -> forAll(laws.updatedRef[A, A](_, _, _))
+ )
}
}
diff --git a/laws/src/main/scala/cats/laws/discipline/UnorderedFoldableTests.scala b/laws/src/main/scala/cats/laws/discipline/UnorderedFoldableTests.scala
index 8eccd46390..29a4e737c9 100644
--- a/laws/src/main/scala/cats/laws/discipline/UnorderedFoldableTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/UnorderedFoldableTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -24,11 +45,15 @@ trait UnorderedFoldableTests[F[_]] extends Laws {
name = "unorderedFoldable",
parent = None,
"unorderedFold consistent with unorderedFoldMap" -> forAll(laws.unorderedFoldConsistentWithUnorderedFoldMap[A] _),
+ "unorderedFoldMapA identity" -> forAll(laws.unorderedFoldMapAIdentity[A, B] _),
"forall consistent with exists" -> forAll(laws.forallConsistentWithExists[A] _),
"forall true if empty" -> forAll(laws.forallEmpty[A] _),
"nonEmpty reference" -> forAll(laws.nonEmptyRef[A] _),
"exists is lazy" -> forAll(laws.existsLazy[A] _),
- "forall is lazy" -> forAll(laws.forallLazy[A] _)
+ "forall is lazy" -> forAll(laws.forallLazy[A] _),
+ "contains consistent with exists" -> forAll(laws.containsConsistentWithExists[A] _),
+ "contains consistent with forall" -> forAll(laws.containsConsistentWithForall[A] _),
+ "contains all elements from itself" -> forAll(laws.containsAllElementsFromItself[A] _)
)
}
diff --git a/laws/src/main/scala/cats/laws/discipline/UnorderedTraverseTests.scala b/laws/src/main/scala/cats/laws/discipline/UnorderedTraverseTests.scala
index cdcb86cf2c..3bfab160ef 100644
--- a/laws/src/main/scala/cats/laws/discipline/UnorderedTraverseTests.scala
+++ b/laws/src/main/scala/cats/laws/discipline/UnorderedTraverseTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -9,9 +30,13 @@ import cats.kernel.CommutativeMonoid
trait UnorderedTraverseTests[F[_]] extends UnorderedFoldableTests[F] {
def laws: UnorderedTraverseLaws[F]
- def unorderedTraverse[A: Arbitrary, B: Arbitrary, C: Arbitrary, X[_]: CommutativeApplicative, Y[
- _
- ]: CommutativeApplicative](implicit
+ def unorderedTraverse[
+ A: Arbitrary,
+ B: Arbitrary,
+ C: Arbitrary,
+ X[_]: CommutativeApplicative,
+ Y[_]: CommutativeApplicative
+ ](implicit
ArbFA: Arbitrary[F[A]],
ArbFXB: Arbitrary[F[X[B]]],
ArbXB: Arbitrary[X[B]],
@@ -26,22 +51,15 @@ trait UnorderedTraverseTests[F[_]] extends UnorderedFoldableTests[F] {
EqXYFC: Eq[X[Y[F[C]]]],
EqXFB: Eq[X[F[B]]],
EqYFB: Eq[Y[F[B]]]
- ): RuleSet = {
- implicit def EqXFBYFB: Eq[(X[F[B]], Y[F[B]])] =
- new Eq[(X[F[B]], Y[F[B]])] {
- override def eqv(x: (X[F[B]], Y[F[B]]), y: (X[F[B]], Y[F[B]])): Boolean =
- EqXFB.eqv(x._1, y._1) && EqYFB.eqv(x._2, y._2)
- }
- new DefaultRuleSet(
- name = "unorderedTraverse",
- parent = Some(unorderedFoldable[A, B]),
- "unordered traverse sequential composition" -> forAll(
- laws.unorderedTraverseSequentialComposition[A, B, C, X, Y] _
- ),
- "unordered traverse parallel composition" -> forAll(laws.unorderedTraverseParallelComposition[A, B, X, Y] _),
- "unordered traverse consistent with sequence" -> forAll(laws.unorderedSequenceConsistent[B, X] _)
- )
- }
+ ): RuleSet = new DefaultRuleSet(
+ name = "unorderedTraverse",
+ parent = Some(unorderedFoldable[A, B]),
+ "unordered traverse sequential composition" -> forAll(
+ laws.unorderedTraverseSequentialComposition[A, B, C, X, Y] _
+ ),
+ "unordered traverse parallel composition" -> forAll(laws.unorderedTraverseParallelComposition[A, B, X, Y] _),
+ "unordered traverse consistent with sequence" -> forAll(laws.unorderedSequenceConsistent[B, X] _)
+ )
}
object UnorderedTraverseTests {
diff --git a/laws/src/main/scala/cats/laws/discipline/arbitrary.scala b/laws/src/main/scala/cats/laws/discipline/arbitrary.scala
index 43b9752137..4016d9ad95 100644
--- a/laws/src/main/scala/cats/laws/discipline/arbitrary.scala
+++ b/laws/src/main/scala/cats/laws/discipline/arbitrary.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
@@ -109,7 +130,20 @@ object arbitrary extends ArbitraryInstances0 with ScalaVersionSpecific.Arbitrary
a <- A.arbitrary
} yield NonEmptyMap((k, a), fa))
- implicit def cogenNonEmptyMap[K: Order: Cogen, A: Order: Cogen]: Cogen[NonEmptyMap[K, A]] =
+ @deprecated("Preserved for bincompat", "2.9.0")
+ def cogenNonEmptyMap[K, A](kOrder: Order[K],
+ kCogen: Cogen[K],
+ aOrder: Order[A],
+ aCogen: Cogen[A]
+ ): Cogen[NonEmptyMap[K, A]] = {
+ implicit val orderingK: Order[K] = kOrder
+ implicit val cogenK: Cogen[K] = kCogen
+ implicit val cogenA: Cogen[A] = aCogen
+
+ cogenNonEmptyMap[K, A]
+ }
+
+ implicit def cogenNonEmptyMap[K: Order: Cogen, A: Cogen]: Cogen[NonEmptyMap[K, A]] =
Cogen[SortedMap[K, A]].contramap(_.toSortedMap)
implicit def catsLawsArbitraryForEitherT[F[_], A, B](implicit
@@ -248,45 +282,38 @@ object arbitrary extends ArbitraryInstances0 with ScalaVersionSpecific.Arbitrary
// implies equal, in order to avoid producing invalid instances.
implicit def catsLawsArbitraryForEq[A: Arbitrary]: Arbitrary[Eq[A]] =
- Arbitrary(
- getArbitrary[Int => Int].map(f =>
- new Eq[A] {
- def eqv(x: A, y: A): Boolean = f(x.##) == f(y.##)
- }
- )
- )
+ Arbitrary(getArbitrary[Int => Int].map(f => Eq.by(x => f(x.##))))
implicit def catsLawsArbitraryForEquiv[A: Arbitrary]: Arbitrary[Equiv[A]] =
Arbitrary(getArbitrary[Eq[A]].map(Eq.catsKernelEquivForEq(_)))
implicit def catsLawsArbitraryForPartialOrder[A: Arbitrary]: Arbitrary[PartialOrder[A]] =
- Arbitrary(
- getArbitrary[Int => Double].map(f =>
- new PartialOrder[A] {
- def partialCompare(x: A, y: A): Double =
- if (x.## == y.##) 0.0 else f(x.##) - f(y.##)
- }
- )
- )
+ Arbitrary(getArbitrary[Int => Double].map(f => PartialOrder.by(x => f(x.##))))
implicit def catsLawsArbitraryForPartialOrdering[A: Arbitrary]: Arbitrary[PartialOrdering[A]] =
Arbitrary(getArbitrary[PartialOrder[A]].map(PartialOrder.catsKernelPartialOrderingForPartialOrder(_)))
implicit def catsLawsArbitraryForOrder[A: Arbitrary]: Arbitrary[Order[A]] =
- Arbitrary(
- getArbitrary[Int => Int].map(f =>
- new Order[A] {
- def compare(x: A, y: A): Int = java.lang.Integer.compare(f(x.##), f(y.##))
- }
- )
- )
+ Arbitrary(getArbitrary[Int => Int].map(f => Order.by(x => f(x.##))))
implicit def catsLawsArbitraryForSortedMap[K: Arbitrary: Order, V: Arbitrary]: Arbitrary[SortedMap[K, V]] =
Arbitrary(getArbitrary[Map[K, V]].map(s => SortedMap.empty[K, V](implicitly[Order[K]].toOrdering) ++ s))
- implicit def catsLawsCogenForSortedMap[K: Order: Cogen, V: Order: Cogen]: Cogen[SortedMap[K, V]] = {
+ @deprecated("Preserved for bincompat", "2.9.0")
+ def catsLawsCogenForSortedMap[K, V](kOrder: Order[K],
+ kCogen: Cogen[K],
+ vOrder: Order[V],
+ vCogen: Cogen[V]
+ ): Cogen[SortedMap[K, V]] = {
+ implicit val orderingK: Order[K] = kOrder
+ implicit val cogenK: Cogen[K] = kCogen
+ implicit val cogenA: Cogen[V] = vCogen
+
+ catsLawsCogenForSortedMap[K, V]
+ }
+
+ implicit def catsLawsCogenForSortedMap[K: Order: Cogen, V: Cogen]: Cogen[SortedMap[K, V]] = {
implicit val orderingK: Ordering[K] = Order[K].toOrdering
- implicit val orderingV: Ordering[V] = Order[V].toOrdering
implicitly[Cogen[Map[K, V]]].contramap(_.toMap)
}
diff --git a/laws/src/main/scala/cats/laws/discipline/package.scala b/laws/src/main/scala/cats/laws/discipline/package.scala
index fba55d6db7..7273d6f132 100644
--- a/laws/src/main/scala/cats/laws/discipline/package.scala
+++ b/laws/src/main/scala/cats/laws/discipline/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
diff --git a/laws/src/main/scala/cats/laws/package.scala b/laws/src/main/scala/cats/laws/package.scala
index aafeffb16e..a4aeca060a 100644
--- a/laws/src/main/scala/cats/laws/package.scala
+++ b/laws/src/main/scala/cats/laws/package.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package object laws {
diff --git a/laws/src/test/scala/cats/laws/discipline/MonadTestsTests.scala b/laws/src/test/scala/cats/laws/discipline/MonadTestsTests.scala
index a5de3524e0..3cce492863 100644
--- a/laws/src/test/scala/cats/laws/discipline/MonadTestsTests.scala
+++ b/laws/src/test/scala/cats/laws/discipline/MonadTestsTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package laws
package discipline
diff --git a/mima.sbt b/mima.sbt
new file mode 100644
index 0000000000..4571afdc5c
--- /dev/null
+++ b/mima.sbt
@@ -0,0 +1,164 @@
+import com.typesafe.tools.mima.core.ProblemFilters._
+import com.typesafe.tools.mima.core._
+
+ThisBuild / mimaBinaryIssueFilters ++= {
+ // These things are Ops classes that shouldn't have the `value` exposed. These should have never been public because they don't
+ // provide any value. Making them private because of issues like #2514 and #2613.
+ Seq(
+ exclude[DirectMissingMethodProblem]("cats.ApplicativeError#LiftFromOptionPartially.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.Const#OfPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.EitherT#CondPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.EitherT#FromEitherPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.EitherT#FromOptionPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.EitherT#LeftPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.EitherT#LeftTPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.EitherT#PurePartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.EitherT#RightPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.IorT#BothTPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.IorT#CondPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.IorT#FromEitherPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.IorT#FromIorPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.IorT#FromOptionPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.IorT#LeftPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.IorT#LeftTPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.IorT#PurePartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.IorT#RightPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.NonEmptyChainOps.value"),
+ exclude[DirectMissingMethodProblem]("cats.data.OptionT#FromOptionPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.OptionT#PurePartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.data.Validated#CatchOnlyPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.free.Free#FreeInjectKPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.free.Free#FreeLiftInjectKPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.free.FreeT#FreeTLiftInjectKPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ApplicativeErrorIdOps.e"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ApplicativeErrorOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ApplicativeIdOps.a"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ApplicativeOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ApplyOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.BinestedIdOps.value"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.BitraverseOps.fab"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.DistributiveOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EitherIdOps.obj"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EitherIdOpsBinCompat0.value"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EitherSyntax#CatchOnlyPartiallyApplied.dummy"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EitherKOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EitherObjectOps.either"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EitherOps.eab"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EitherOpsBinCompat0.value"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.FlatMapIdOps.a"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.FlatMapOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.FlatMapOptionOps.fopta"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.FlattenOps.ffa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.FoldableOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.GuardOps.condition"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.IfMOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.IndexOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.IorIdOps.a"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.LeftOps.left"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ListOps.la"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ListOpsBinCompat0.la"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.MonadErrorOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.MonadErrorRethrowOps.fea"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.MonadIdOps.a"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.MonadOps.fa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.MonoidOps.lhs"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.NestedBitraverseOps.fgagb"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.NestedFoldableOps.fga"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.NestedIdOps.value"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.NestedReducibleOps.fga"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.OptionIdOps.a"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.OptionOps.oa"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ParallelApOps.ma"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ParallelFlatSequenceOps.tmta"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ParallelFlatTraversableOps.ta"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ParallelSequence_Ops.tma"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ParallelSequenceOps.tma"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ParallelTraversable_Ops.ta"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ParallelTraversableOps.ta"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.RightOps.right"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.SeparateOps.fgab"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.SetOps.se"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.TabulateOps.f"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.TryOps.self"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.UniteOps.fga"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ValidatedExtension.self"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ValidatedIdOpsBinCompat0.a"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.ValidatedIdSyntax.a"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.VectorOps.va"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.WriterIdSyntax.a")
+ ) ++ // Only compile-time abstractions (macros) allowed here
+ Seq(
+ exclude[IncompatibleMethTypeProblem]("cats.arrow.FunctionKMacros.lift"),
+ exclude[MissingTypesProblem]("cats.arrow.FunctionKMacros$"),
+ exclude[IncompatibleMethTypeProblem]("cats.arrow.FunctionKMacros#Lifter.this"),
+ exclude[IncompatibleResultTypeProblem]("cats.arrow.FunctionKMacros#Lifter.c"),
+ exclude[DirectMissingMethodProblem]("cats.arrow.FunctionKMacros.compatNewTypeName")
+ ) ++ // package private classes no longer needed
+ Seq(
+ exclude[MissingClassProblem]("cats.kernel.compat.scalaVersionMoreSpecific$"),
+ exclude[MissingClassProblem]("cats.kernel.compat.scalaVersionMoreSpecific"),
+ exclude[MissingClassProblem](
+ "cats.kernel.compat.scalaVersionMoreSpecific$suppressUnusedImportWarningForScalaVersionMoreSpecific"
+ )
+ ) ++ // New issues found since mima 0.8.0 (#3596, #3641)
+ Seq(
+ exclude[NewMixinForwarderProblem]("cats.kernel.Band#mcI#sp.combineN"),
+ exclude[NewMixinForwarderProblem]("cats.kernel.Band#mcD#sp.combineN"),
+ exclude[NewMixinForwarderProblem]("cats.kernel.Band#mcJ#sp.combineN"),
+ exclude[NewMixinForwarderProblem]("cats.kernel.Band.combineN"),
+ exclude[NewMixinForwarderProblem]("cats.kernel.Band#mcF#sp.combineN")
+ ) ++ // Additional methods in package-private traits
+ Seq(
+ exclude[ReversedMissingMethodProblem]("cats.data.NonEmptyCollection.grouped")
+ ) ++ // https://github.com/typelevel/cats/pull/3785
+ Seq(
+ exclude[MissingClassProblem]("cats.syntax.EqOps$mcJ$sp"),
+ exclude[MissingClassProblem]("cats.syntax.EqOps$mcD$sp"),
+ exclude[FinalClassProblem]("cats.syntax.EqOps"),
+ exclude[MissingFieldProblem]("cats.syntax.EqOps.lhs"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.unapply"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.apply"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.lhs"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy$default$1"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productPrefix"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productArity"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productElement"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productIterator"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.canEqual"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy$default$1$mcD$sp"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy$default$1$mcF$sp"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy$default$1$mcJ$sp"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.copy$default$1$mcI$sp"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productElementNames"),
+ exclude[DirectMissingMethodProblem]("cats.syntax.EqOps.productElementName"),
+ exclude[MissingClassProblem]("cats.syntax.EqOps$"),
+ exclude[MissingClassProblem]("cats.syntax.EqOps$mcF$sp"),
+ exclude[MissingClassProblem]("cats.syntax.EqOps$mcI$sp")
+ ) ++ // https://github.com/typelevel/cats/pull/3918
+ Seq(
+ exclude[MissingClassProblem]("algebra.laws.IsSerializable"),
+ exclude[MissingClassProblem]("algebra.laws.IsSerializable$")
+ ) ++ // https://github.com/typelevel/cats/pull/3987
+ Seq(
+ exclude[DirectAbstractMethodProblem]("cats.free.ContravariantCoyoneda.k"),
+ exclude[ReversedAbstractMethodProblem]("cats.free.ContravariantCoyoneda.k"),
+ exclude[DirectAbstractMethodProblem]("cats.free.Coyoneda.k"),
+ exclude[ReversedAbstractMethodProblem]("cats.free.Coyoneda.k")
+ ) ++ // https://github.com/typelevel/cats/pull/4315
+ Seq(
+ exclude[MissingClassProblem]("cats.compat.compat$package"),
+ exclude[MissingClassProblem]("cats.compat.compat$package$"),
+ ProblemFilters.exclude[MissingClassProblem]("cats.compat.targetName")
+ ) ++ // scala 3 specific filters
+ Seq(
+ exclude[DirectMissingMethodProblem]("cats.free.ContravariantCoyoneda.unsafeApply"),
+ exclude[DirectMissingMethodProblem]("cats.free.Coyoneda.unsafeApply")
+ ) ++ Seq(
+ ProblemFilters.exclude[MissingClassProblem]("cats.compat.package"),
+ ProblemFilters.exclude[MissingClassProblem]("cats.compat.package$")
+ ) ++ Seq( // PR#4682
+ // Renamed to `cats.Traverse.traverseVoidDirectly`
+ ProblemFilters.exclude[DirectMissingMethodProblem]("cats.Traverse.traverse_Directly")
+ )
+}
diff --git a/native/src/test/scala/cats/native/tests/FutureSuite.scala b/native/src/test/scala/cats/native/tests/FutureSuite.scala
deleted file mode 100644
index 3536b7a7a6..0000000000
--- a/native/src/test/scala/cats/native/tests/FutureSuite.scala
+++ /dev/null
@@ -1,65 +0,0 @@
-package cats.native.tests
-
-import cats.kernel.laws.discipline.{MonoidTests => MonoidLawTests, SemigroupTests => SemigroupLawTests}
-import cats.kernel.{Eq, Semigroup}
-import cats.laws.discipline._
-import cats.laws.discipline.arbitrary._
-import cats.syntax.either._
-import cats.tests.{CatsSuite, ListWrapper}
-import org.scalacheck.Arbitrary.arbitrary
-import org.scalacheck.rng.Seed
-import org.scalacheck.{Arbitrary, Cogen}
-
-import scala.concurrent.{Await, ExecutionContextExecutor, Future}
-import scala.concurrent.duration._
-
-class FutureSuite extends CatsSuite {
- val timeout = 3.seconds
-
- // TODO: We shouldn't do this! See: https://github.com/scala-js/scala-js/issues/2102
- implicit private object SynchronousExecutor extends ExecutionContextExecutor {
- def execute(runnable: Runnable): Unit =
- try {
- runnable.run()
- } catch {
- case t: Throwable => reportFailure(t)
- }
-
- def reportFailure(t: Throwable): Unit =
- t.printStackTrace()
- }
-
- def futureEither[A](f: Future[A]): Future[Either[Throwable, A]] =
- f.map(Either.right[Throwable, A]).recover { case t => Either.left(t) }
-
- implicit def eqfa[A: Eq]: Eq[Future[A]] =
- new Eq[Future[A]] {
- def eqv(fx: Future[A], fy: Future[A]): Boolean = {
- val fz = futureEither(fx).zip(futureEither(fy))
- Await.result(fz.map { case (tx, ty) => tx === ty }, timeout)
- }
- }
-
- implicit def cogen[A: Cogen]: Cogen[Future[A]] =
- Cogen[Future[A]] { (seed: Seed, t: Future[A]) =>
- Cogen[A].perturb(seed, Await.result(t, timeout))
- }
-
- implicit val throwableEq: Eq[Throwable] =
- Eq.by[Throwable, String](_.toString)
-
- // Need non-fatal Throwables for Future recoverWith/handleError
- implicit val nonFatalArbitrary: Arbitrary[Throwable] =
- Arbitrary(arbitrary[Exception].map(identity))
-
- checkAll("Future with Throwable", MonadErrorTests[Future, Throwable].monadError[Int, Int, Int])
- checkAll("Future", MonadTests[Future].monad[Int, Int, Int])
- checkAll("Future", CoflatMapTests[Future].coflatMap[Int, Int, Int])
-
- {
- implicit val F: Semigroup[ListWrapper[Int]] = ListWrapper.semigroup[Int]
- checkAll("Future[ListWrapper[Int]]", SemigroupLawTests[Future[ListWrapper[Int]]].semigroup)
- }
-
- checkAll("Future[Int]", MonoidLawTests[Future[Int]].monoid)
-}
diff --git a/project/AlgebraBoilerplate.scala b/project/AlgebraBoilerplate.scala
index cac6c3f7ee..6f5b0528ec 100644
--- a/project/AlgebraBoilerplate.scala
+++ b/project/AlgebraBoilerplate.scala
@@ -44,9 +44,7 @@ object AlgebraBoilerplate {
val synVals = (0 until arity).map(n => s"a$n")
val `A..N` = synTypes.mkString(", ")
val `a..n` = synVals.mkString(", ")
- val `_.._` = Seq.fill(arity)("_").mkString(", ")
val `(A..N)` = if (arity == 1) "Tuple1[A0]" else synTypes.mkString("(", ", ", ")")
- val `(_.._)` = if (arity == 1) "Tuple1[_]" else Seq.fill(arity)("_").mkString("(", ", ", ")")
val `(a..n)` = if (arity == 1) "Tuple1(a)" else synVals.mkString("(", ", ", ")")
}
@@ -86,32 +84,32 @@ object AlgebraBoilerplate {
import tv._
def constraints(constraint: String) =
- synTypes.map(tpe => s"${tpe}: ${constraint}[${tpe}]").mkString(", ")
+ synTypes.map(tpe => s"$tpe: $constraint[$tpe]").mkString(", ")
def tuple(results: TraversableOnce[String]) = {
val resultsVec = results.toVector
val a = synTypes.size
val r = s"${0.until(a).map(i => resultsVec(i)).mkString(", ")}"
if (a == 1) "Tuple1(" ++ r ++ ")"
- else s"(${r})"
+ else s"($r)"
}
def binMethod(name: String) =
synTypes.zipWithIndex.iterator.map { case (tpe, i) =>
val j = i + 1
- s"${tpe}.${name}(x._${j}, y._${j})"
+ s"$tpe.$name(x._$j, y._$j)"
}
def binTuple(name: String) =
tuple(binMethod(name))
def unaryTuple(name: String) = {
- val m = synTypes.zipWithIndex.map { case (tpe, i) => s"${tpe}.${name}(x._${i + 1})" }
+ val m = synTypes.zipWithIndex.map { case (tpe, i) => s"$tpe.$name(x._${i + 1})" }
tuple(m)
}
def nullaryTuple(name: String) = {
- val m = synTypes.map(tpe => s"${tpe}.${name}")
+ val m = synTypes.map(tpe => s"$tpe.$name")
tuple(m)
}
@@ -125,34 +123,34 @@ object AlgebraBoilerplate {
-
- implicit def tuple${arity}Rig[${`A..N`}](implicit ${constraints("Rig")}): Rig[${`(A..N)`}] =
- new Rig[${`(A..N)`}] {
- - def one: ${`(A..N)`} = ${nullaryTuple("one")}
- - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("plus")}
- - def times(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("times")}
- - def zero: ${`(A..N)`} = ${nullaryTuple("zero")}
+ - def zero = ${nullaryTuple("zero")}
+ - def one = ${nullaryTuple("one")}
+ - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("plus")}
+ - def times(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("times")}
- }
-
- implicit def tuple${arity}Ring[${`A..N`}](implicit ${constraints("Ring")}): Ring[${`(A..N)`}] =
- new Ring[${`(A..N)`}] {
- - def one: ${`(A..N)`} = ${nullaryTuple("one")}
- - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("plus")}
- - def times(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("times")}
- - def zero: ${`(A..N)`} = ${nullaryTuple("zero")}
- - def negate(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("negate")}
+ - def zero = ${nullaryTuple("zero")}
+ - def one = ${nullaryTuple("one")}
+ - def negate(x: ${`(A..N)`}) = ${unaryTuple("negate")}
+ - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("plus")}
+ - def times(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("times")}
- }
-
- implicit def tuple${arity}Rng[${`A..N`}](implicit ${constraints("Rng")}): Rng[${`(A..N)`}] =
- new Rng[${`(A..N)`}] {
- - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("plus")}
- - def times(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("times")}
- - def zero: ${`(A..N)`} = ${nullaryTuple("zero")}
- - def negate(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("negate")}
+ - def zero = ${nullaryTuple("zero")}
+ - def negate(x: ${`(A..N)`}) = ${unaryTuple("negate")}
+ - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("plus")}
+ - def times(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("times")}
- }
-
- implicit def tuple${arity}Semiring[${`A..N`}](implicit ${constraints("Semiring")}): Semiring[${`(A..N)`}] =
- new Semiring[${`(A..N)`}] {
- - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("plus")}
- - def times(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("times")}
- - def zero: ${`(A..N)`} = ${nullaryTuple("zero")}
+ - def zero = ${nullaryTuple("zero")}
+ - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("plus")}
+ - def times(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("times")}
- }
|}
"""
diff --git a/project/Boilerplate.scala b/project/Boilerplate.scala
index 978c99ffaf..58955aa3c4 100644
--- a/project/Boilerplate.scala
+++ b/project/Boilerplate.scala
@@ -27,10 +27,12 @@ object Boilerplate {
GenSemigroupalBuilders,
GenSemigroupalArityFunctions,
GenApplyArityFunctions,
+ GenFlatMapArityFunctions,
GenTupleSemigroupalSyntax,
GenParallelArityFunctions,
GenParallelArityFunctions2,
GenFoldableArityFunctions,
+ GenFunctionSyntax,
GenTupleParallelSyntax,
GenTupleShowInstances,
GenTupleMonadInstances,
@@ -59,9 +61,7 @@ object Boilerplate {
val synTypedVals = synVals.zip(synTypes).map { case (v, t) => v + ":" + t }
val `A..N` = synTypes.mkString(", ")
val `a..n` = synVals.mkString(", ")
- val `_.._` = Seq.fill(arity)("_").mkString(", ")
val `(A..N)` = if (arity == 1) "Tuple1[A0]" else synTypes.mkString("(", ", ", ")")
- val `(_.._)` = if (arity == 1) "Tuple1[_]" else Seq.fill(arity)("_").mkString("(", ", ", ")")
val `(a..n)` = if (arity == 1) "Tuple1(a)" else synVals.mkString("(", ", ", ")")
val `a:A..n:N` = synTypedVals.mkString(", ")
@@ -74,10 +74,6 @@ object Boilerplate {
if (arity <= 2) "(*, *)"
else `A..(N - 2)`.mkString("(", ", ", ", *, *)")
val `a..(n - 1)` = (0 until (arity - 1)).map(n => s"a$n")
- val `fa._1..fa._(n - 2)` =
- if (arity <= 2) "" else (0 until (arity - 2)).map(n => s"fa._${n + 1}").mkString("", ", ", ", ")
- val `pure(fa._1..(n - 2))` =
- if (arity <= 2) "" else (0 until (arity - 2)).map(n => s"G.pure(fa._${n + 1})").mkString("", ", ", ", ")
val `a0, a(n - 1)` = if (arity <= 1) "" else `a..(n - 1)`.mkString(", ")
val `[A0, A(N - 1)]` = if (arity <= 1) "" else `A..(N - 1)`.mkString("[", ", ", "]")
val `(A0, A(N - 1))` =
@@ -87,19 +83,15 @@ object Boilerplate {
val `(A..N - 1, *)` =
if (arity == 1) "Tuple1"
else `A..(N - 1)`.mkString("(", ", ", ", *)")
- val `(fa._1..(n - 1))` =
- if (arity <= 1) "Tuple1.apply" else (0 until (arity - 1)).map(n => s"fa._${n + 1}").mkString("(", ", ", ", _)")
def `A0, A(N - 1)&`(a: String): String =
if (arity <= 1) s"Tuple1[$a]" else `A..(N - 1)`.mkString("(", ", ", s", $a)")
-
- def `fa._1..(n - 1) & `(a: String): String =
- if (arity <= 1) s"Tuple1($a)" else (0 until (arity - 1)).map(n => s"fa._${n + 1}").mkString("(", ", ", s", $a)")
-
- def `constraints A..N`(c: String): String = synTypes.map(tpe => s"$tpe: $c[$tpe]").mkString("(implicit ", ", ", ")")
+ def `constraints A..N`(c: String): String =
+ synTypes.map(tpe => s"$tpe: $c[$tpe]").mkString("(implicit ", ", ", ")")
def `constraints A..(N-1)`(c: String): String =
if (arity <= 1) "" else `A..(N - 1)`.map(tpe => s"$tpe: $c[$tpe]").mkString("(implicit ", ", ", ")")
- def `parameters A..(N-1)`(c: String): String = `A..(N - 1)`.map(tpe => s"$tpe: $c[$tpe]").mkString(", ")
+ def `parameters A..(N-1)`(c: String): String =
+ `A..(N - 1)`.map(tpe => s"$tpe: $c[$tpe]").mkString(", ")
}
trait Template {
@@ -279,7 +271,37 @@ object Boilerplate {
- /** @group MapArity */
- def map$arity[${`A..N`}, Z]($fparams)(f: (${`A..N`}) => Z): F[Z] = Semigroupal.map$arity($fparams)(f)(self, self)
- /** @group TupleArity */
- - def tuple$arity[${`A..N`}, Z]($fparams): F[(${`A..N`})] = Semigroupal.tuple$arity($fparams)(self, self)
+ - def tuple$arity[${`A..N`}]($fparams): F[(${`A..N`})] = Semigroupal.tuple$arity($fparams)(self, self)
+ |}
+ """
+ }
+ }
+
+ object GenFlatMapArityFunctions extends Template {
+ def filename(root: File) = root / "cats" / "FlatMapArityFunctions.scala"
+ override def range = 2 to maxArity
+ def content(tv: TemplateVals) = {
+ import tv._
+
+ val vals = (0 until arity).map("f" + _)
+ val tpes = synTypes.map(tpe => s"F[$tpe]")
+ val fargs = vals.mkString(", ")
+ val fparams = vals.zip(tpes).map { case (v, t) => s"$v:$t" }.mkString(", ")
+
+ block"""
+ |package cats
+ |
+ |/**
+ | * @groupprio Ungrouped 0
+ | *
+ | * @groupname FlatMapArity flatMap arity
+ | * @groupdesc FlatMapArity Higher-arity flatMap methods
+ | * @groupprio FlatMapArity 999
+ | */
+ |trait FlatMapArityFunctions[F[_]] { self: FlatMap[F] =>
+ - /** @group FlatMapArity */
+ - def flatMap$arity[${`A..N`}, Z]($fparams)(f: (${`A..N`}) => F[Z]): F[Z] =
+ - flatten(map$arity($fargs)(f))
|}
"""
}
@@ -318,6 +340,9 @@ object Boilerplate {
- /** @group ParMapArity */
- def parMap$arity[M[_], ${`A..N`}, Z]($fparams)(f: (${`A..N`}) => Z)(implicit p: NonEmptyParallel[M]): M[Z] =
- p.flatMap.map(${nestedExpansion.products}) { case ${nestedExpansion.`(a..n)`} => f(${`a..n`}) }
+ -
+ - def parFlatMap$arity[M[_], ${`A..N`}, Z]($fparams)(f: (${`A..N`}) => M[Z])(implicit p: NonEmptyParallel[M]): M[Z] =
+ - p.flatMap.flatMap(${nestedExpansion.products}) { case ${nestedExpansion.`(a..n)`} => f(${`a..n`}) }
|}
"""
}
@@ -329,12 +354,10 @@ object Boilerplate {
def content(tv: TemplateVals) = {
import tv._
- val tpes = synTypes.map { tpe =>
- s"M[$tpe]"
- }
- val fargs = (0 until arity).map("m" + _)
- val fparams = fargs.zip(tpes).map { case (v, t) => s"$v:$t" }.mkString(", ")
- val nestedExpansion = ParallelNestedExpansions(arity)
+ val vals = (0 until arity).map("m" + _)
+ val tpes = synTypes.map(tpe => s"M[$tpe]")
+ val fargs = vals.mkString(", ")
+ val fparams = vals.zip(tpes).map { case (v, t) => s"$v:$t" }.mkString(", ")
block"""
|package cats
@@ -349,7 +372,7 @@ object Boilerplate {
|abstract class ParallelArityFunctions2 extends ParallelArityFunctions {
- /** @group ParTupleArity */
- def parTuple$arity[M[_], ${`A..N`}]($fparams)(implicit p: NonEmptyParallel[M]): M[(${`A..N`})] =
- - p.flatMap.map(${nestedExpansion.products}) { case ${nestedExpansion.`(a..n)`} => (${`a..n`}) }
+ - parMap$arity($fargs)(Tuple$arity.apply)
|}
"""
}
@@ -411,7 +434,7 @@ object Boilerplate {
- invariant.imap($nestedProducts) { case ${`nested (a..n)`} => f(${`a..n`}) } { z => val ${`(a..n)`} = g(z); ${`nested (a..n)`} }
- /** @group TupleArity */
- def tuple$arity[F[_], ${`A..N`}]($fparams)(implicit semigroupal: Semigroupal[F], invariant: Invariant[F]):F[(${`A..N`})] =
- - imap$arity($fargsS)((${`_.._`}))(identity)
+ - imap$arity($fargsS)(Tuple$arity.apply)(identity)
- /** @group TraverseArity */
- def traverse$arity[F[_], G[_], ${`A..N`}, Z]($fparams)(f: (${`A..N`}) => G[Z])(implicit semigroupal: Semigroupal[F], traverse: Traverse[F], applicative: Applicative[G]): G[F[Z]] =
- traverse.traverse($nestedProducts) { case ${`nested (a..n)`} => f(${`a..n`}) }
@@ -426,20 +449,9 @@ object Boilerplate {
def content(tv: TemplateVals) = {
import tv._
- val tpes = synTypes.map { tpe =>
- s"M[$tpe]"
- }
- val tpesString = tpes.mkString(", ")
-
- val tuple = s"Tuple$arity[$tpesString]"
- val tupleTpe = s"t$arity: $tuple"
- val tupleArgs = (1 to arity).map(n => s"t$arity._$n").mkString(", ")
-
- val n = if (arity == 1) {
- ""
- } else {
- arity.toString
- }
+ val tpes = synTypes.map(tpe => s"M[$tpe]")
+ val tuple = if (arity == 1) s"Tuple1[${tpes.head}]" else tpes.mkString("(", ", ", ")")
+ val tupleArgs = (1 to arity).map(n => s"t._$n").mkString(", ")
val parMap =
if (arity == 1)
@@ -447,10 +459,14 @@ object Boilerplate {
else
s"def parMapN[Z](f: (${`A..N`}) => Z)(implicit p: NonEmptyParallel[M]): M[Z] = Parallel.parMap$arity($tupleArgs)(f)"
+ val parFlatMap =
+ if (arity == 1)
+ s"def parFlatMap[Z](f: (${`A..N`}) => M[Z])(implicit p: NonEmptyParallel[M]): M[Z] = p.flatMap.flatMap($tupleArgs)(f)"
+ else
+ s"def parFlatMapN[Z](f: (${`A..N`}) => M[Z])(implicit p: NonEmptyParallel[M]): M[Z] = Parallel.parFlatMap$arity($tupleArgs)(f)"
val parTupled =
if (arity == 1) ""
- else
- s"def parTupled(implicit p: NonEmptyParallel[M]): M[(${`A..N`})] = Parallel.parTuple$arity($tupleArgs)"
+ else s"def parTupled(implicit p: NonEmptyParallel[M]): M[(${`A..N`})] = Parallel.parTuple$arity($tupleArgs)"
block"""
|package cats
@@ -459,12 +475,13 @@ object Boilerplate {
|import cats.Parallel
|
|trait TupleParallelSyntax {
- - implicit def catsSyntaxTuple${arity}Parallel[M[_], ${`A..N`}]($tupleTpe): Tuple${arity}ParallelOps[M, ${`A..N`}] = new Tuple${arity}ParallelOps(t$arity)
+ - implicit def catsSyntaxTuple${arity}Parallel[M[_], ${`A..N`}](t: $tuple): Tuple${arity}ParallelOps[M, ${`A..N`}] = new Tuple${arity}ParallelOps(t)
|}
|
- -private[syntax] final class Tuple${arity}ParallelOps[M[_], ${`A..N`}](private val $tupleTpe) extends Serializable {
+ -private[syntax] final class Tuple${arity}ParallelOps[M[_], ${`A..N`}](private val t: $tuple) extends Serializable {
- $parMap
- $parTupled
+ - $parFlatMap
-}
|
"""
@@ -477,20 +494,10 @@ object Boilerplate {
def content(tv: TemplateVals) = {
import tv._
- val tpes = synTypes.map { tpe =>
- s"F[$tpe]"
- }
- val tpesString = tpes.mkString(", ")
-
- val tuple = s"Tuple$arity[$tpesString]"
- val tupleTpe = s"t$arity: $tuple"
- val tupleArgs = (1 to arity).map(n => s"t$arity._$n").mkString(", ")
-
- val n = if (arity == 1) {
- ""
- } else {
- arity.toString
- }
+ val tpes = synTypes.map(tpe => s"F[$tpe]")
+ val tuple = if (arity == 1) s"Tuple1[${tpes.head}]" else tpes.mkString("(", ", ", ")")
+ val tupleArgs = (1 to arity).map(n => s"t._$n").mkString(", ")
+ val n = if (arity == 1) "" else arity.toString
val map =
if (arity == 1)
@@ -510,11 +517,10 @@ object Boilerplate {
else
s"def imapN[Z](f: (${`A..N`}) => Z)(g: Z => (${`A..N`}))(implicit invariant: Invariant[F], semigroupal: Semigroupal[F]): F[Z] = Semigroupal.imap$arity($tupleArgs)(f)(g)"
- val tupled = if (arity != 1) {
- s"def tupled(implicit invariant: Invariant[F], semigroupal: Semigroupal[F]): F[(${`A..N`})] = Semigroupal.tuple$n($tupleArgs)"
- } else {
- ""
- }
+ val tupled =
+ if (arity == 1) ""
+ else
+ s"def tupled(implicit invariant: Invariant[F], semigroupal: Semigroupal[F]): F[(${`A..N`})] = Semigroupal.tuple$n($tupleArgs)"
val traverse =
if (arity == 1)
@@ -522,21 +528,31 @@ object Boilerplate {
else
s"def traverseN[G[_]: Applicative, Z](f: (${`A..N`}) => G[Z])(implicit traverse: Traverse[F], semigroupal: Semigroupal[F]): G[F[Z]] = Semigroupal.traverse$arity($tupleArgs)(f)"
+ val flatMap =
+ if (arity == 1)
+ s"def flatMap[Z](f: (${`A..N`}) => F[Z])(implicit flatMap: FlatMap[F]): F[Z] = flatMap.flatMap($tupleArgs)(f)"
+ else
+ s"def flatMapN[Z](f: (${`A..N`}) => F[Z])(implicit flatMap: FlatMap[F]): F[Z] = flatMap.flatMap$arity($tupleArgs)(f)"
+
+ val apWith =
+ s"def apWith[Z](f: F[(${`A..N`}) => Z])(implicit apply: Apply[F]): F[Z] = apply.ap$n(f)($tupleArgs)"
+
block"""
|package cats
|package syntax
|
|trait TupleSemigroupalSyntax {
- - implicit def catsSyntaxTuple${arity}Semigroupal[F[_], ${`A..N`}]($tupleTpe): Tuple${arity}SemigroupalOps[F, ${`A..N`}] = new Tuple${arity}SemigroupalOps(t$arity)
+ - implicit def catsSyntaxTuple${arity}Semigroupal[F[_], ${`A..N`}](t: $tuple): Tuple${arity}SemigroupalOps[F, ${`A..N`}] = new Tuple${arity}SemigroupalOps(t)
|}
|
- -private[syntax] final class Tuple${arity}SemigroupalOps[F[_], ${`A..N`}](private val $tupleTpe) extends Serializable {
+ -private[syntax] final class Tuple${arity}SemigroupalOps[F[_], ${`A..N`}](private val t: $tuple) extends Serializable {
- $map
- $contramap
- $imap
+ - $flatMap
- $tupled
- $traverse
- - def apWith[Z](f: F[(${`A..N`}) => Z])(implicit apply: Apply[F]): F[Z] = apply.ap$n(f)($tupleArgs)
+ - $apWith
-}
|
"""
@@ -549,9 +565,8 @@ object Boilerplate {
def content(tv: TemplateVals) = {
import tv._
- val tupleTpe = (1 to arity).map(_ => "A").mkString("(", ", ", ")")
- def listXN(range: Range) = range.map("x" + _).mkString(" :: ")
- val tupleXN = (1 to arity).map("x" + _).mkString("(", ", ", ")")
+ val tupleTpe = Iterator.fill(arity)("A").mkString("(", ", ", ")")
+ val tupleXN = Iterator.tabulate(arity)(i => s"x($i)").mkString("(", ", ", ")")
block"""
|package cats
@@ -562,7 +577,7 @@ object Boilerplate {
| * @groupname FoldableSlidingN foldable arity
| * @groupdesc FoldableSlidingN
| * Group sequential elements into fixed sized tuples by passing a "sliding window" over them.
- | *
+ | *
| * A foldable with fewer elements than the window size will return an empty list unlike `Iterable#sliding(size: Int)`.
| * Example:
| * {{{
@@ -572,28 +587,60 @@ object Boilerplate {
| *
| * scala> Foldable[List].sliding4((1 to 10).toList)
| * val res1: List[(Int, Int, Int, Int)] = List((1,2,3,4), (2,3,4,5), (3,4,5,6), (4,5,6,7), (5,6,7,8), (6,7,8,9), (7,8,9,10))
- | *
+ | *
| * scala> Foldable[List].sliding4((1 to 2).toList)
| * val res2: List[(Int, Int, Int, Int)] = List()
| *
| * }}}
- | *
+ | *
| * @groupprio FoldableSlidingN 999
| *
| */
|trait FoldableNFunctions[F[_]] { self: Foldable[F] =>
+ | private def slidingN[A, B](fa: F[A], n: Int)(f: Seq[A] => B) =
+ | toIterable(fa).iterator.sliding(n).withPartial(false).map(f).toList
+ |
- /** @group FoldableSlidingN */
- def sliding$arity[A](fa: F[A]): List[$tupleTpe] =
- - foldRight(fa, Now((List.empty[$tupleTpe], List.empty[A]))) { (x1, eval) =>
- - val (acc, l) = eval.value
- - l match {
- - case ${listXN(2 to arity)} :: Nil =>
- - Now(($tupleXN :: acc, ${listXN(1 until arity)} :: Nil))
- - case l =>
- - Now((acc, x1 :: l))
- - }
- - }.value._1
+ - slidingN(fa, $arity)(x => $tupleXN)
+ |}
+ """
+ }
+ }
+
+ object GenFunctionSyntax extends Template {
+ def filename(root: File) = root / "cats" / "syntax" / "FunctionApplySyntax.scala"
+
+ override def range = 2 to maxArity
+
+ def content(tv: TemplateVals) = {
+ import tv._
+
+ val function = s"Function$arity[${`A..N`}, T]"
+
+ val typedParams = synVals.zip(synTypes).map { case (v, t) => s"$v: F[$t]" }.mkString(", ")
+
+ block"""
+ |package cats
+ |package syntax
+ |
+ |import cats.Functor
+ |import cats.Semigroupal
+ |
+ |trait FunctionApplySyntax {
+ | implicit def catsSyntaxFunction1Apply[T, A0](f: Function1[A0, T]): Function1ApplyOps[T, A0] = new Function1ApplyOps(f)
+ - implicit def catsSyntaxFunction${arity}Apply[T, ${`A..N`}](f: $function): Function${arity}ApplyOps[T, ${`A..N`}] = new Function${arity}ApplyOps(f)
+ |}
+ |
+ |private[syntax] final class Function1ApplyOps[T, A0](private val f: Function1[A0, T]) extends AnyVal with Serializable {
+ | def liftN[F[_]: Functor](a0: F[A0]): F[T] = Functor[F].map(a0)(f)
+ | def parLiftN[F[_]: Functor](a0: F[A0]): F[T] = Functor[F].map(a0)(f)
|}
+ |
+ -private[syntax] final class Function${arity}ApplyOps[T, ${`A..N`}](private val f: $function) extends AnyVal with Serializable {
+ - def liftN[F[_]: Functor: Semigroupal]($typedParams): F[T] = Semigroupal.map$arity(${`a..n`})(f)
+ - def parLiftN[F[_]: Parallel]($typedParams): F[T] = Parallel.parMap$arity(${`a..n`})(f)
+ -}
"""
}
}
diff --git a/project/KernelBoiler.scala b/project/KernelBoiler.scala
index 207a2b5ec7..c12e42483e 100644
--- a/project/KernelBoiler.scala
+++ b/project/KernelBoiler.scala
@@ -1,4 +1,3 @@
-import KernelBoiler.TemplateVals
import sbt._
/**
@@ -82,40 +81,40 @@ object KernelBoiler {
abstract class TemplatedBlock(tv: TemplateVals) {
import tv._
- def constraints(constraint: String) =
- synTypes.map(tpe => s"${tpe}: ${constraint}[${tpe}]").mkString(", ")
+ def constraints(constraint: String): String =
+ synTypes.map(tpe => s"$tpe: $constraint[$tpe]").mkString(", ")
- def tuple(results: TraversableOnce[String]) = {
+ def tuple(results: TraversableOnce[String]): String = {
val resultsVec = results.toVector
val a = synTypes.size
val r = s"${0.until(a).map(i => resultsVec(i)).mkString(", ")}"
if (a == 1) "Tuple1(" ++ r ++ ")"
- else s"(${r})"
+ else s"($r)"
}
def tupleNHeader = s"Tuple${synTypes.size}"
- def binMethod(name: String) =
+ def binMethod(name: String): Iterator[String] =
synTypes.zipWithIndex.iterator.map { case (tpe, i) =>
val j = i + 1
- s"${tpe}.${name}(x._${j}, y._${j})"
+ s"$tpe.$name(x._$j, y._$j)"
}
- def binTuple(name: String) =
+ def binTuple(name: String): String =
tuple(binMethod(name))
- def unaryTuple(name: String) = {
- val m = synTypes.zipWithIndex.map { case (tpe, i) => s"${tpe}.${name}(x._${i + 1})" }
+ def unaryTuple(name: String): String = {
+ val m = synTypes.zipWithIndex.map { case (tpe, i) => s"$tpe.$name(x._${i + 1})" }
tuple(m)
}
- def unaryMethod(name: String) =
+ def unaryMethod(name: String): Iterator[String] =
synTypes.zipWithIndex.iterator.map { case (tpe, i) =>
s"$tpe.$name(x._${i + 1})"
}
- def nullaryTuple(name: String) = {
- val m = synTypes.map(tpe => s"${tpe}.${name}")
+ def nullaryTuple(name: String): String = {
+ val m = synTypes.map(tpe => s"$tpe.$name")
tuple(m)
}
@@ -142,26 +141,19 @@ object KernelBoiler {
import tv._
def content =
block"""
- | implicit def catsKernelStdCommutativeGroupForTuple${arity}[${`A..N`}](implicit ${constraints(
- "CommutativeGroup"
- )}): CommutativeGroup[${`(A..N)`}] =
- | new CommutativeGroup[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
- | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")}
- | }
- | implicit def catsKernelStdOrderForTuple${arity}[${`A..N`}](implicit ${constraints("Order")}): Order[${`(A..N)`}] =
- | new Order[${`(A..N)`}] {
- | def compare(x: ${`(A..N)`}, y: ${`(A..N)`}): Int =
- | ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0)
- | }
- | implicit def catsKernelStdBoundedSemilatticeForTuple${arity}[${`A..N`}](implicit ${constraints(
- "BoundedSemilattice"
- )}): BoundedSemilattice[${`(A..N)`}] =
- | new BoundedSemilattice[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
- | }"""
+ | implicit def catsKernelStdCommutativeGroupForTuple$arity[${`A..N`}](
+ | implicit ${constraints("CommutativeGroup")}
+ | ): CommutativeGroup[${`(A..N)`}] =
+ | Semigroup.catsKernelCommutativeGroupForTuple$arity[${`A..N`}]
+ | implicit def catsKernelStdOrderForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Order")}
+ | ): Order[${`(A..N)`}] =
+ | Eq.catsKernelOrderForTuple$arity[${`A..N`}]
+ | implicit def catsKernelStdBoundedSemilatticeForTuple$arity[${`A..N`}](
+ | implicit ${constraints("BoundedSemilattice")}
+ | ): BoundedSemilattice[${`(A..N)`}] =
+ | Semigroup.catsKernelBoundedSemilatticeForTuple$arity[${`A..N`}]
+ |"""
}
),
InstanceDef(
@@ -172,38 +164,27 @@ object KernelBoiler {
import tv._
def content =
block"""
- | implicit def catsKernelStdSemilatticeForTuple${arity}[${`A..N`}](implicit ${constraints(
- "Semilattice"
- )}): Semilattice[${`(A..N)`}] =
- | new Semilattice[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | }
- | implicit def catsKernelStdCommutativeMonoidForTuple${arity}[${`A..N`}](implicit ${constraints(
- "CommutativeMonoid"
- )}): CommutativeMonoid[${`(A..N)`}] =
- | new CommutativeMonoid[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
- | }
- | implicit def catsKernelStdGroupForTuple${arity}[${`A..N`}](implicit ${constraints("Group")}): Group[${`(A..N)`}] =
- | new Group[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
- | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")}
- | }
- | implicit def catsKernelStdHashForTuple${arity}[${`A..N`}](implicit ${constraints("Hash")}): Hash[${`(A..N)`}] =
- | new Hash[${`(A..N)`}] {
- | def hash(x: ${`(A..N)`}): Int = ${unaryMethod("hash")
- .mkString(s"$tupleNHeader(", ", ", ")")}.hashCode()
- | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = ${binMethod("eqv").mkString(" && ")}
- | }
- | implicit def catsKernelStdPartialOrderForTuple${arity}[${`A..N`}](implicit ${constraints(
- "PartialOrder"
- )}): PartialOrder[${`(A..N)`}] =
- | new PartialOrder[${`(A..N)`}] {
- | def partialCompare(x: ${`(A..N)`}, y: ${`(A..N)`}): Double =
- | ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0)
- | }"""
+ | implicit def catsKernelStdSemilatticeForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Semilattice")}
+ | ): Semilattice[${`(A..N)`}] =
+ | Semigroup.catsKernelSemilatticeForTuple$arity[${`A..N`}]
+ | implicit def catsKernelStdCommutativeMonoidForTuple$arity[${`A..N`}](
+ | implicit ${constraints("CommutativeMonoid")}
+ | ): CommutativeMonoid[${`(A..N)`}] =
+ | Semigroup.catsKernelCommutativeMonoidForTuple$arity[${`A..N`}]
+ | implicit def catsKernelStdGroupForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Group")}
+ | ): Group[${`(A..N)`}] =
+ | Semigroup.catsKernelGroupForTuple$arity[${`A..N`}]
+ | implicit def catsKernelStdHashForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Hash")}
+ | ): Hash[${`(A..N)`}] =
+ | Eq.catsKernelHashForTuple$arity[${`A..N`}]
+ | implicit def catsKernelStdPartialOrderForTuple$arity[${`A..N`}](
+ | implicit ${constraints("PartialOrder")}
+ | ): PartialOrder[${`(A..N)`}] =
+ | Eq.catsKernelPartialOrderForTuple$arity[${`A..N`}]
+ |"""
}
),
InstanceDef(
@@ -214,21 +195,19 @@ object KernelBoiler {
import tv._
def content =
block"""
- | implicit def catsKernelStdBandForTuple${arity}[${`A..N`}](implicit ${constraints("Band")}): Band[${`(A..N)`}] =
- | new Band[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | }
- | implicit def catsKernelStdCommutativeSemigroupForTuple${arity}[${`A..N`}](implicit ${constraints(
- "CommutativeSemigroup"
- )}): CommutativeSemigroup[${`(A..N)`}] =
- | new CommutativeSemigroup[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | }
- | implicit def catsKernelStdMonoidForTuple${arity}[${`A..N`}](implicit ${constraints("Monoid")}): Monoid[${`(A..N)`}] =
- | new Monoid[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
- | }"""
+ | implicit def catsKernelStdBandForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Band")}
+ | ): Band[${`(A..N)`}] =
+ | Semigroup.catsKernelBandForTuple$arity[${`A..N`}]
+ | implicit def catsKernelStdCommutativeSemigroupForTuple$arity[${`A..N`}](
+ | implicit ${constraints("CommutativeSemigroup")}
+ | ): CommutativeSemigroup[${`(A..N)`}] =
+ | Semigroup.catsKernelCommutativeSemigroupForTuple$arity[${`A..N`}]
+ | implicit def catsKernelStdMonoidForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Monoid")}
+ | ): Monoid[${`(A..N)`}] =
+ | Semigroup.catsKernelMonoidForTuple$arity[${`A..N`}]
+ |"""
}
),
InstanceDef(
@@ -239,14 +218,15 @@ object KernelBoiler {
import tv._
def content =
block"""
- | implicit def catsKernelStdSemigroupForTuple${arity}[${`A..N`}](implicit ${constraints("Semigroup")}): Semigroup[${`(A..N)`}] =
- | new Semigroup[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | }
- | implicit def catsKernelStdEqForTuple${arity}[${`A..N`}](implicit ${constraints("Eq")}): Eq[${`(A..N)`}] =
- | new Eq[${`(A..N)`}] {
- | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = ${binMethod("eqv").mkString(" && ")}
- | }"""
+ | implicit def catsKernelStdSemigroupForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Semigroup")}
+ | ): Semigroup[${`(A..N)`}] =
+ | Semigroup.catsKernelSemigroupForTuple$arity[${`A..N`}]
+ | implicit def catsKernelStdEqForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Eq")}
+ | ): Eq[${`(A..N)`}] =
+ | Eq.catsKernelEqForTuple$arity[${`A..N`}]
+ |"""
}
),
InstanceDef(
@@ -255,9 +235,12 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelBandForTuple${arity}[${`A..N`}](implicit ${constraints("Band")}): Band[${`(A..N)`}] = new Band[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | }"""
+ block"""
+ | implicit def catsKernelBandForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Band")}
+ | ): Band[${`(A..N)`}] = Band.instance { (x, y) =>
+ | ${binTuple("combine")}
+ | }"""
}
),
InstanceDef(
@@ -266,12 +249,13 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelBoundedSemilatticeForTuple${arity}[${`A..N`}](implicit ${constraints(
- "BoundedSemilattice"
- )}): BoundedSemilattice[${`(A..N)`}] = new BoundedSemilattice[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
- | }"""
+ block"""
+ | implicit def catsKernelBoundedSemilatticeForTuple$arity[${`A..N`}](
+ | implicit ${constraints("BoundedSemilattice")}
+ | ): BoundedSemilattice[${`(A..N)`}] = BoundedSemilattice.instance(
+ | ${nullaryTuple("empty")},
+ | (x, y) => ${binTuple("combine")}
+ | )"""
}
),
InstanceDef(
@@ -280,13 +264,14 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelCommutativeGroupForTuple${arity}[${`A..N`}](implicit ${constraints(
- "CommutativeGroup"
- )}): CommutativeGroup[${`(A..N)`}] = new CommutativeGroup[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
- | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")}
- | }"""
+ block"""
+ | implicit def catsKernelCommutativeGroupForTuple$arity[${`A..N`}](
+ | implicit ${constraints("CommutativeGroup")}
+ | ): CommutativeGroup[${`(A..N)`}] = new CommutativeGroup[${`(A..N)`}] {
+ | def empty = ${nullaryTuple("empty")}
+ | def inverse(x: ${`(A..N)`}) = ${unaryTuple("inverse")}
+ | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("combine")}
+ | }"""
}
),
InstanceDef(
@@ -295,12 +280,13 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelCommutativeMonoidForTuple${arity}[${`A..N`}](implicit ${constraints(
- "CommutativeMonoid"
- )}): CommutativeMonoid[${`(A..N)`}] = new CommutativeMonoid[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
- | }"""
+ block"""
+ | implicit def catsKernelCommutativeMonoidForTuple$arity[${`A..N`}](
+ | implicit ${constraints("CommutativeMonoid")}
+ | ): CommutativeMonoid[${`(A..N)`}] = CommutativeMonoid.instance(
+ | ${nullaryTuple("empty")},
+ | (x, y) => ${binTuple("combine")}
+ | )"""
}
),
InstanceDef(
@@ -309,11 +295,12 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelCommutativeSemigroupForTuple${arity}[${`A..N`}](implicit ${constraints(
- "CommutativeSemigroup"
- )}): CommutativeSemigroup[${`(A..N)`}] = new CommutativeSemigroup[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | }"""
+ block"""
+ | implicit def catsKernelCommutativeSemigroupForTuple$arity[${`A..N`}](
+ | implicit ${constraints("CommutativeSemigroup")}
+ | ): CommutativeSemigroup[${`(A..N)`}] = CommutativeSemigroup.instance { (x, y) =>
+ | ${binTuple("combine")}
+ | }"""
}
),
InstanceDef(
@@ -322,9 +309,12 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelEqForTuple${arity}[${`A..N`}](implicit ${constraints("Eq")}): Eq[${`(A..N)`}] = new Eq[${`(A..N)`}] {
- | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = ${binMethod("eqv").mkString(" && ")}
- | }"""
+ block"""
+ | implicit def catsKernelEqForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Eq")}
+ | ): Eq[${`(A..N)`}] = Eq.instance { (x, y) =>
+ | ${binMethod("eqv").mkString(" && ")}
+ | }"""
}
),
InstanceDef(
@@ -333,11 +323,14 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelGroupForTuple${arity}[${`A..N`}](implicit ${constraints("Group")}): Group[${`(A..N)`}] = new Group[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
- | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")}
- | }"""
+ block"""
+ | implicit def catsKernelGroupForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Group")}
+ | ): Group[${`(A..N)`}] = new Group[${`(A..N)`}] {
+ | def empty = ${nullaryTuple("empty")}
+ | def inverse(x: ${`(A..N)`}) = ${unaryTuple("inverse")}
+ | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("combine")}
+ | }"""
}
),
InstanceDef(
@@ -346,11 +339,15 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelHashForTuple${arity}[${`A..N`}](implicit ${constraints("Hash")}): Hash[${`(A..N)`}] = new Hash[${`(A..N)`}] {
- | def hash(x: ${`(A..N)`}): Int = ${unaryMethod("hash")
- .mkString(s"$tupleNHeader(", ", ", ")")}.hashCode()
- | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = ${binMethod("eqv").mkString(" && ")}
- | }"""
+ block"""
+ | implicit def catsKernelHashForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Hash")}
+ | ): Hash[${`(A..N)`}] = new Hash[${`(A..N)`}] {
+ | def hash(x: ${`(A..N)`}) =
+ | ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode()
+ | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}) =
+ | ${binMethod("eqv").mkString(" && ")}
+ | }"""
}
),
InstanceDef(
@@ -359,10 +356,13 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelMonoidForTuple${arity}[${`A..N`}](implicit ${constraints("Monoid")}): Monoid[${`(A..N)`}] = new Monoid[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
- | }"""
+ block"""
+ | implicit def catsKernelMonoidForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Monoid")}
+ | ): Monoid[${`(A..N)`}] = Monoid.instance(
+ | ${nullaryTuple("empty")},
+ | (x, y) => ${binTuple("combine")}
+ | )"""
}
),
InstanceDef(
@@ -371,10 +371,12 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelOrderForTuple${arity}[${`A..N`}](implicit ${constraints("Order")}): Order[${`(A..N)`}] = new Order[${`(A..N)`}] {
- | def compare(x: ${`(A..N)`}, y: ${`(A..N)`}): Int =
- | ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0)
- | }"""
+ block"""
+ | implicit def catsKernelOrderForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Order")}
+ | ): Order[${`(A..N)`}] = Order.from { (x, y) =>
+ | ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0)
+ | }"""
}
),
InstanceDef(
@@ -383,12 +385,12 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelPartialOrderForTuple${arity}[${`A..N`}](implicit ${constraints(
- "PartialOrder"
- )}): PartialOrder[${`(A..N)`}] = new PartialOrder[${`(A..N)`}] {
- | def partialCompare(x: ${`(A..N)`}, y: ${`(A..N)`}): Double =
- | ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0)
- | }"""
+ block"""
+ | implicit def catsKernelPartialOrderForTuple$arity[${`A..N`}](
+ | implicit ${constraints("PartialOrder")}
+ | ): PartialOrder[${`(A..N)`}] = PartialOrder.from { (x, y) =>
+ | ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0)
+ | }"""
}
),
InstanceDef(
@@ -397,11 +399,12 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelSemigroupForTuple${arity}[${`A..N`}](implicit ${constraints(
- "Semigroup"
- )}): Semigroup[${`(A..N)`}] = new Semigroup[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | }"""
+ block"""
+ | implicit def catsKernelSemigroupForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Semigroup")}
+ | ): Semigroup[${`(A..N)`}] = Semigroup.instance { (x, y) =>
+ | ${binTuple("combine")}
+ | }"""
}
),
InstanceDef(
@@ -410,11 +413,12 @@ object KernelBoiler {
new TemplatedBlock(tv) {
import tv._
def content =
- block"""| implicit def catsKernelSemilatticeForTuple${arity}[${`A..N`}](implicit ${constraints(
- "Semilattice"
- )}): Semilattice[${`(A..N)`}] = new Semilattice[${`(A..N)`}] {
- | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
- | }"""
+ block"""
+ | implicit def catsKernelSemilatticeForTuple$arity[${`A..N`}](
+ | implicit ${constraints("Semilattice")}
+ | ): Semilattice[${`(A..N)`}] = Semilattice.instance { (x, y) =>
+ | ${binTuple("combine")}
+ | }"""
}
)
)
diff --git a/project/TupleBifunctorInstancesBoiler.scala b/project/TupleBifunctorInstancesBoiler.scala
index e88baaf60a..b4e151ee98 100644
--- a/project/TupleBifunctorInstancesBoiler.scala
+++ b/project/TupleBifunctorInstancesBoiler.scala
@@ -5,7 +5,7 @@ import Boilerplate.{Template, TemplateVals}
import sbt.File
object GenTupleBifunctorInstances extends Template {
- override def range = 1 to 11
+ override def range = 2 to 11
override def filename(root: sbt.File): File =
root / "cats" / "instances" / "NTupleBifunctorInstances.scala"
@@ -18,15 +18,17 @@ object GenTupleBifunctorInstances extends Template {
|package instances
|
|private[cats] trait NTupleBifunctorInstances {
-${if (arity > 1)
- block"""
+ |
+ | private def instance[F[_, _]](bim: (F[Any, Any], Any => Any, Any => Any) => F[Any, Any]): Bifunctor[F] =
+ | new Bifunctor[F] {
+ | def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D] =
+ | bim(fab.asInstanceOf[F[Any, Any]], f.asInstanceOf[Any => Any], g.asInstanceOf[Any => Any]).asInstanceOf[F[C, D]]
+ | }
+ -
- implicit final def catsStdBifunctorForTuple$arity${`[A0, A(N - 2)]`}: Bifunctor[${`(A..N - 2, *, *)`}] =
- - new Bifunctor[${`(A..N - 2, *, *)`}] {
- - def bimap[A, B, C, D](fa: (${`A0, A(N - 2)`}A, B))(f: A => C, g: B => D): (${`A0, A(N - 2)`}C, D) = (${`fa._1..fa._(n - 2)`}f(fa._${arity - 1}), g(fa._$arity))
- - }"""
- else
- block"""
- -"""}
+ - instance[${`(A..N - 2, *, *)`}] { (fab, f, g) =>
+ - fab.copy(_${arity - 1} = f(fab._${arity - 1}), _$arity = g(fab._$arity))
+ - }
|}"""
}
}
diff --git a/project/TupleBitraverseInstancesBoiler.scala b/project/TupleBitraverseInstancesBoiler.scala
index 4933d44f07..7b13ab0aea 100644
--- a/project/TupleBitraverseInstancesBoiler.scala
+++ b/project/TupleBitraverseInstancesBoiler.scala
@@ -5,7 +5,7 @@ import Boilerplate.{Template, TemplateVals}
import sbt.File
object GenTupleBitraverseInstances extends Template {
- override def range = 1 to 11
+ override def range = 2 to 11
override def filename(root: sbt.File): File =
root / "cats" / "instances" / "NTupleBitraverseInstances.scala"
@@ -18,20 +18,35 @@ object GenTupleBitraverseInstances extends Template {
|package instances
|
|private[cats] trait NTupleBitraverseInstances {
-${if (arity > 1)
- block"""
+ | protected type γ[_]
+ |
+ | private def instance[F[_, _] <: Product](
+ | bitrav: (F[Any, Any], Applicative[γ], Any => γ[Any], Any => γ[Any]) => γ[F[Any, Any]]
+ | ): Bitraverse[F] = new Bitraverse[F] {
+ | def bitraverse[G[_], A, B, C, D](fab: F[A, B])(f: A => G[C], g: B => G[D])(implicit G: Applicative[G]): G[F[C, D]] =
+ | bitrav(
+ | fab.asInstanceOf[F[Any, Any]],
+ | G.asInstanceOf[Applicative[γ]],
+ | f.asInstanceOf[Any => γ[Any]],
+ | g.asInstanceOf[Any => γ[Any]]
+ | ).asInstanceOf[G[F[C, D]]]
+ |
+ | @inline private def last1[A, B](fab: F[A, B]): A =
+ | fab.productElement(fab.productArity - 2).asInstanceOf[A]
+ | @inline private def last2[A, B](fab: F[A, B]): B =
+ | fab.productElement(fab.productArity - 1).asInstanceOf[B]
+ | def bifoldLeft[A, B, C](fab: F[A, B], c: C)(f: (C, A) => C, g: (C, B) => C): C =
+ | g(f(c, last1(fab)), last2(fab))
+ | def bifoldRight[A, B, C](fab: F[A, B], c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] =
+ | g(last2(fab), f(last1(fab), c))
+ | }
+ -
- implicit final def catsStdBitraverseForTuple$arity${`[A0, A(N - 2)]`}: Bitraverse[${`(A..N - 2, *, *)`}] =
- - new Bitraverse[${`(A..N - 2, *, *)`}] {
- - def bitraverse[G[_], A, B, C, D](fa: (${`A0, A(N - 2)`}A, B))(f: A => G[C], g: B => G[D])(implicit G: Applicative[G]): G[(${`A0, A(N - 2)`}C, D)] =
- - G.tuple$arity(${`pure(fa._1..(n - 2))`}f(fa._${arity - 1}), g(fa._$arity))
- - def bifoldLeft[A, B, C](fa: (${`A0, A(N - 2)`}A, B), c: C)(f: (C, A) => C, g: (C, B) => C): C =
- - g(f(c, fa._${arity - 1}), fa._$arity)
- - def bifoldRight[A, B, C](fa: (${`A0, A(N - 2)`}A, B), c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] =
- - g(fa._$arity, f(fa._${arity - 1}, c))
- - }"""
- else
- block"""
- -"""}
+ - instance { (fab, G, f, g) =>
+ - G.map2(f(fab._${arity - 1}), g(fab._$arity)) { (x, y) =>
+ - fab.copy(_${arity - 1} = x, _$arity = y)
+ - }
+ - }
|}"""
}
}
diff --git a/project/TupleMonadInstancesBoiler.scala b/project/TupleMonadInstancesBoiler.scala
index c38cb33449..46f66d7440 100644
--- a/project/TupleMonadInstancesBoiler.scala
+++ b/project/TupleMonadInstancesBoiler.scala
@@ -12,6 +12,9 @@ object GenTupleMonadInstances extends Template {
override def content(tv: TemplateVals): String = {
import tv._
+ val `b..(n - 1)` = for (n <- 0 until arity - 1) yield s"b$n"
+ val `b:A..(n - 1):(N - 1)` = (for ((v, t) <- `b..(n - 1)`.zip(`A..(N - 1)`)) yield s"$v: $t").mkString(", ")
+
/**
* This special case for N = 2 is needed because
* of the deprecated versions in TupleInstances.
@@ -21,31 +24,51 @@ object GenTupleMonadInstances extends Template {
val flatMapTupleClass = if (arity == 2) "FlatMapNTuple2" else s"FlatMapTuple$arity"
def `combine A..(N - 1)`(a: String, b: String, last: String): String =
- if (arity <= 1) s"Tuple1($last)"
+ if (arity <= 1)
+ s"Tuple1($last)"
else
- `A..(N - 1)`.zipWithIndex.iterator
- .map { case (an, i) =>
- s"$an.combine($a._${i + 1}, $b._${i + 1})"
- }
+ `A..(N - 1)`.iterator.zipWithIndex
+ .map { case (an, i) => s"$an.combine($a._${i + 1}, $b._${i + 1})" }
.mkString("(", ", ", s", $last)")
- val coflattenReturn =
- if (arity <= 1) "Tuple1[Tuple1[A]]"
- else
- s"${`A0, A(N - 1)&`(`A0, A(N - 1)&`("A"))}"
-
val monadPureMethod: String =
if (arity <= 1) "Tuple1(a)"
else `A..(N - 1)`.map(n => s"$n.empty").mkString("(", ", ", ", a)")
val tailRecMCombine =
- if (arity == 2) s"A0.combine(x, a0)"
+ `A..(N - 1)`.iterator.zipWithIndex
+ .map { case (an, i) => s"$an.combine(b$i, a$i)" }
+ .mkString(", ")
+
+ val tailRecMMethod =
+ if (arity == 1)
+ block"""
+ - @tailrec
+ - def loop(a: A): Tuple1[B] =
+ - f(a) match {
+ - case Tuple1(Right(b)) => Tuple1(b)
+ - case Tuple1(Left(nextA)) => loop(nextA)
+ - }
+ - loop(a)
+ """
else
- `A..(N - 1)`.zipWithIndex.iterator
- .map { case (an, i) =>
- s"$an.combine(x._${i + 1}, a$i)"
- }
- .mkString(", ")
+ block"""
+ - @tailrec
+ - def loop(${`b:A..(n - 1):(N - 1)`}, a: A): ${`A0, A(N - 1)&`("B")} =
+ - f(a) match {
+ - case (${`a0, a(n - 1)`}, Right(b)) => ($tailRecMCombine, b)
+ - case (${`a0, a(n - 1)`}, Left(nextA)) => loop($tailRecMCombine, nextA)
+ - }
+ - f(a) match {
+ - case (${`a0, a(n - 1)`}, Right(b)) => (${`a0, a(n - 1)`}, b)
+ - case (${`a0, a(n - 1)`}, Left(nextA)) => loop(${`a0, a(n - 1)`}, nextA)
+ - }
+ """
+
+ val `:CommutativeMonoid` = `constraints A..(N-1)`("CommutativeMonoid")
+ val `:CommutativeSemigroup` = `constraints A..(N-1)`("CommutativeSemigroup")
+ val `:Monoid` = `constraints A..(N-1)`("Monoid")
+ val `:Semigroup` = `constraints A..(N-1)`("Semigroup")
block"""
|
@@ -56,100 +79,67 @@ object GenTupleMonadInstances extends Template {
|import scala.annotation.tailrec
|
|private[cats] trait NTupleMonadInstances extends NTupleMonadInstances1 {
+ |
+ | private def instance[F[_] <: Product](cofMap: (F[Any], F[Any] => Any) => F[Any]): Comonad[F] =
+ | new Comonad[F] {
+ | def coflatMap[A, B](fa: F[A])(f: F[A] => B) =
+ | cofMap(fa.asInstanceOf[F[Any]], f.asInstanceOf[F[Any] => Any]).asInstanceOf[F[B]]
+ | def extract[A](fa: F[A]) =
+ | fa.productElement(fa.productArity - 1).asInstanceOf[A]
+ | def map[A, B](fa: F[A])(f: A => B) =
+ | coflatMap(fa)(fa => f(extract(fa)))
+ | }
+ -
- implicit final def catsStdInstancesForTuple$arity${`[A0, A(N - 1)]`}: Comonad[${`(A..N - 1, *)`}] =
- - new Comonad[${`(A..N - 1, *)`}] {
- - def coflatMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: (${`A0, A(N - 1)&`("A")}) => B): ${`A0, A(N - 1)&`(
- "B"
- )} = ${`fa._1..(n - 1) & `(
- "f(fa)"
- )}
- - def extract[A](fa: ${`A0, A(N - 1)&`("A")}): A = fa._$arity
- - override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B): ${`A0, A(N - 1)&`("B")} =
- - ${`fa._1..(n - 1) & `(s"f(fa._$arity)")}
- - override def coflatten[A](fa: ${`A0, A(N - 1)&`("A")}): $coflattenReturn = ${`fa._1..(n - 1) & `("fa")}
- - }
+ - instance((fa, f) => fa.copy(_$arity = f(fa)))
|}
- |private[cats] sealed trait NTupleMonadInstances1 extends NTupleMonadInstances2 {
- - implicit final def catsStdCommutativeMonadForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`(
- "CommutativeMonoid"
- )}: CommutativeMonad[${`(A..N - 1, *)`}] =
+ |private[cats] sealed trait NTupleMonadInstances1 extends NTupleMonadInstances2 { this: NTupleMonadInstances =>
+ - implicit final def catsStdCommutativeMonadForTuple$arity${`[A0, A(N - 1)]`}${`:CommutativeMonoid`}: CommutativeMonad[${`(A..N - 1, *)`}] =
- new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with CommutativeMonad[${`(A..N - 1, *)`}] {
- - def pure[A](a: A): ${`A0, A(N - 1)&`("A")} = $monadPureMethod
+ - def pure[A](a: A) = $monadPureMethod
- }
|}
- |private[cats] sealed trait NTupleMonadInstances2 extends NTupleMonadInstances3 {
- - implicit final def catsStdCommutativeFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`(
- "CommutativeSemigroup"
- )}: CommutativeFlatMap[${`(A..N - 1, *)`}] =
+ |private[cats] sealed trait NTupleMonadInstances2 extends NTupleMonadInstances3 { this: NTupleMonadInstances =>
+ - implicit final def catsStdCommutativeFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`:CommutativeSemigroup`}: CommutativeFlatMap[${`(A..N - 1, *)`}] =
- new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with CommutativeFlatMap[${`(A..N - 1, *)`}]
|}
- |private[cats] sealed trait NTupleMonadInstances3 extends NTupleMonadInstances4 {
- - implicit def catsStdMonadForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`("Monoid")}: Monad[${`(A..N - 1, *)`}] =
+ |private[cats] sealed trait NTupleMonadInstances3 extends NTupleMonadInstances4 { this: NTupleMonadInstances =>
+ - implicit def catsStdMonadForTuple$arity${`[A0, A(N - 1)]`}${`:Monoid`}: Monad[${`(A..N - 1, *)`}] =
- new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with Monad[${`(A..N - 1, *)`}] {
- - def pure[A](a: A): ${`A0, A(N - 1)&`("A")} = $monadPureMethod
+ - def pure[A](a: A) = $monadPureMethod
- }
|}
- |private[cats] sealed trait NTupleMonadInstances4 extends NTupleMonadInstances5 {
- - implicit def catsStdFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`("Semigroup")}: FlatMap[${`(A..N - 1, *)`}] =
+ |private[cats] sealed trait NTupleMonadInstances4 extends NTupleMonadInstances5 { this: NTupleMonadInstances =>
+ - implicit def catsStdFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`:Semigroup`}: FlatMap[${`(A..N - 1, *)`}] =
- new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`})
|}
- |private[cats] sealed trait NTupleMonadInstances5 {
+ |private[cats] sealed trait NTupleMonadInstances5 { this: NTupleMonadInstances =>
- implicit def catsStdInvariantForTuple$arity${`[A0, A(N - 1)]`}: Invariant[${`(A..N - 1, *)`}] =
- - new Invariant[${`(A..N - 1, *)`}] {
- - def imap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: B => A): ${`A0, A(N - 1)&`("B")} =
- - ${`fa._1..(n - 1) & `(s"f(fa._$arity)")}
- - }
+ - catsStdInstancesForTuple$arity
|}
-
- -private[instances] class $flatMapTupleClass${`[A0, A(N - 1)]`}(${`parameters A..(N-1)`("Semigroup")}) extends FlatMap[${`(A..N - 1, *)`}] {
- - override def ap[A, B](ff: ${`A0, A(N - 1)&`("A => B")})(fa: ${`A0, A(N - 1)&`("A")}): ${`A0, A(N - 1)&`("B")} =
+ -private[instances] class $flatMapTupleClass${`[A0, A(N - 1)]`}(${`parameters A..(N-1)`("Semigroup")})
+ - extends FlatMap[${`(A..N - 1, *)`}] {
+ - override def ap[A, B](ff: ${`A0, A(N - 1)&`("A => B")})(fa: ${`A0, A(N - 1)&`("A")}) =
- ${`combine A..(N - 1)`("ff", "fa", s"ff._$arity(fa._$arity)")}
- - override def product[A, B](fa: ${`A0, A(N - 1)&`("A")}, fb: ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("(A, B)")} =
+ - override def product[A, B](fa: ${`A0, A(N - 1)&`("A")}, fb: ${`A0, A(N - 1)&`("B")}) =
- ${`combine A..(N - 1)`("fa", "fb", s"(fa._$arity, fb._$arity)")}
- - override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B): ${`A0, A(N - 1)&`("B")} =
- - ${`fa._1..(n - 1) & `(s"f(fa._$arity)")}
- - def flatMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("B")} = {
- ${if (arity > 1) block"""
- - val xb = f(fa._$arity)
- - ${`combine A..(N - 1)`("fa", "xb", s"xb._$arity")}
- """
- else block"""
- - f(fa._1)
- """}
+ - override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B) =
+ - fa.copy(_$arity = f(fa._$arity))
+ - def flatMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => ${`A0, A(N - 1)&`("B")}) = {
+ - val xb = f(fa._$arity)
+ - ${`combine A..(N - 1)`("fa", "xb", s"xb._$arity")}
- }
- - override def productR[A, B](a: ${`A0, A(N - 1)&`("A")})(b: ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("B")} =
+ - override def productR[A, B](a: ${`A0, A(N - 1)&`("A")})(b: ${`A0, A(N - 1)&`("B")}) =
- ${`combine A..(N - 1)`("a", "b", s"b._$arity")}
- - override def productL[A, B](a: ${`A0, A(N - 1)&`("A")})(b: ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("A")} =
+ - override def productL[A, B](a: ${`A0, A(N - 1)&`("A")})(b: ${`A0, A(N - 1)&`("B")}) =
- ${`combine A..(N - 1)`("a", "b", s"a._$arity")}
- - override def mproduct[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`(
- "(A, B)"
- )} = {
+ - override def mproduct[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => ${`A0, A(N - 1)&`("B")}) = {
- val xb = f(fa._$arity)
- ${`combine A..(N - 1)`("fa", "xb", s"(fa._$arity, xb._$arity)")}
- }
- - def tailRecM[A, B](a: A)(f: A => ${`A0, A(N - 1)&`("Either[A, B]")}): ${`A0, A(N - 1)&`("B")} = {
- - @tailrec
-${if (arity > 1) block"""
- - def loop(x: ${`(A0, A(N - 1))`}, aa: A): ${`A0, A(N - 1)&`("B")} =
- - f(aa) match {
- - case (${`a0, a(n - 1)`}, Right(b)) => ($tailRecMCombine, b)
- - case (${`a0, a(n - 1)`}, Left(nextA)) => loop(($tailRecMCombine), nextA)
- - }
- - f(a) match {
- - case (${`a0, a(n - 1)`}, Right(b)) => (${`a0, a(n - 1)`}, b)
- - case (${`a0, a(n - 1)`}, Left(nextA)) => loop((${`a0, a(n - 1)`}), nextA)
-"""
- else block"""
- - def loop(aa: A): Tuple1[B] =
- - f(aa) match {
- - case Tuple1(Right(b)) => Tuple1(b)
- - case Tuple1(Left(nextA)) => loop(nextA)
- - }
- - f(a) match {
- - case Tuple1(Right(b)) => Tuple1(b)
- - case Tuple1(Left(nextA)) => loop(nextA)
- """}
- - }
+ - def tailRecM[A, B](a: A)(f: A => ${`A0, A(N - 1)&`("Either[A, B]")}) = {
+ - $tailRecMMethod
- }
-}"""
}
diff --git a/project/TupleShowInstancesBoiler.scala b/project/TupleShowInstancesBoiler.scala
index f3273683d8..d590d26e3c 100644
--- a/project/TupleShowInstancesBoiler.scala
+++ b/project/TupleShowInstancesBoiler.scala
@@ -26,9 +26,7 @@ object GenTupleShowInstances extends Template {
|
|private[cats] trait NTupleShowInstances {
- implicit final def catsStdShowForTuple$arity[${`A..N`}]${`constraints A..N`("Show")}: Show[${`(A..N)`}] =
- - new Show[${`(A..N)`}] {
- - def show(f: ${`(A..N)`}): String = $showMethod
- - }
+ - Show.show(f => $showMethod)
|}"""
}
}
diff --git a/project/TupleUnorderedFoldableInstancesBoiler.scala b/project/TupleUnorderedFoldableInstancesBoiler.scala
index cf9fbfe8d4..224e277f73 100644
--- a/project/TupleUnorderedFoldableInstancesBoiler.scala
+++ b/project/TupleUnorderedFoldableInstancesBoiler.scala
@@ -18,33 +18,37 @@ object GenTupleUnorderedFoldableInstances extends Template {
|package instances
|
|private[cats] trait NTupleUnorderedFoldableInstances {
-- implicit final def catsUnorderedFoldableInstancesForTuple$arity${`[A0, A(N - 1)]`}: Traverse[${`(A..N - 1, *)`}] with Reducible[${`(A..N - 1, *)`}] =
-- new Traverse[${`(A..N - 1, *)`}] with Reducible[${`(A..N - 1, *)`}] {
-- def traverse[G[_], A, B](fa: ${`A0, A(N - 1)&`(
- "A"
- )})(f: A => G[B])(implicit G: Applicative[G]): G[${`A0, A(N - 1)&`(
- "B"
- )}] =
-- G.map(f(fa._$arity))(${`(fa._1..(n - 1))`})
-- def foldLeft[A, B](fa: ${`A0, A(N - 1)&`("A")}, b: B)(f: (B, A) => B): B = f(b, fa._$arity)
-- def foldRight[A, B](fa: ${`A0, A(N - 1)&`("A")}, lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = f(fa._$arity, lb)
-- override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B): ${`A0, A(N - 1)&`("B")} =
-- ${`fa._1..(n - 1) & `(s"f(fa._$arity)")}
-- override def foldMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(implicit B: Monoid[B]): B = f(fa._$arity)
-- override def reduce[A](fa: ${`A0, A(N - 1)&`("A")})(implicit A: Semigroup[A]): A = fa._$arity
-- def reduceLeftTo[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: (B, A) => B): B = f(fa._$arity)
-- override def reduceLeft[A](fa: ${`A0, A(N - 1)&`("A")})(f: (A, A) => A): A = fa._$arity
-- override def reduceLeftToOption[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: (B, A) => B): Option[B] = Some(f(fa._$arity))
-- override def reduceRight[A](fa: ${`A0, A(N - 1)&`("A")})(f: (A, Eval[A]) => Eval[A]): Eval[A] = Now(fa._$arity)
-- def reduceRightTo[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] = Now(f(fa._$arity))
-- override def reduceRightToOption[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[Option[B]] = Now(Some(f(fa._$arity)))
-- override def reduceMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(implicit B: Semigroup[B]): B = f(fa._$arity)
-- override def size[A](fa: ${`A0, A(N - 1)&`("A")}): Long = 1L
-- override def get[A](fa: ${`A0, A(N - 1)&`("A")})(idx: Long): Option[A] = if (idx == 0L) Some(fa._$arity) else None
-- override def exists[A](fa: ${`A0, A(N - 1)&`("A")})(p: A => Boolean): Boolean = p(fa._$arity)
-- override def forall[A](fa: ${`A0, A(N - 1)&`("A")})(p: A => Boolean): Boolean = p(fa._$arity)
-- override def isEmpty[A](fa: ${`A0, A(N - 1)&`("A")}): Boolean = false
-- }
+ | protected type γ[_]
+ |
+ | private def instance[F[_] <: Product](
+ | trav: (F[Any], Applicative[γ], Any => γ[Any]) => γ[F[Any]]
+ | ): Traverse[F] with Reducible[F] =
+ | new Traverse[F] with Reducible[F] {
+ | def traverse[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]) =
+ | trav(fa.asInstanceOf[F[Any]], G.asInstanceOf[Applicative[γ]], f.asInstanceOf[Any => γ[Any]]).asInstanceOf[G[F[B]]]
+ | @inline private def last[A](fa: F[A]): A =
+ | fa.productElement(fa.productArity - 1).asInstanceOf[A]
+ | def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B = f(b, last(fa))
+ | def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = f(last(fa), lb)
+ | override def foldMap[A, B](fa: F[A])(f: A => B)(implicit B: Monoid[B]): B = f(last(fa))
+ | override def reduce[A](fa: F[A])(implicit A: Semigroup[A]): A = last(fa)
+ | def reduceLeftTo[A, B](fa: F[A])(f: A => B)(g: (B, A) => B): B = f(last(fa))
+ | override def reduceLeft[A](fa: F[A])(f: (A, A) => A): A = last(fa)
+ | override def reduceLeftToOption[A, B](fa: F[A])(f: A => B)(g: (B, A) => B): Option[B] = Some(f(last(fa)))
+ | override def reduceRight[A](fa: F[A])(f: (A, Eval[A]) => Eval[A]): Eval[A] = Now(last(fa))
+ | def reduceRightTo[A, B](fa: F[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] = Now(f(last(fa)))
+ | override def reduceRightToOption[A, B](fa: F[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[Option[B]] = Now(Some(f(last(fa))))
+ | override def reduceMap[A, B](fa: F[A])(f: A => B)(implicit B: Semigroup[B]): B = f(last(fa))
+ | override def size[A](fa: F[A]): Long = 1L
+ | override def get[A](fa: F[A])(idx: Long): Option[A] = if (idx == 0L) Some(last(fa)) else None
+ | override def exists[A](fa: F[A])(p: A => Boolean): Boolean = p(last(fa))
+ | override def forall[A](fa: F[A])(p: A => Boolean): Boolean = p(last(fa))
+ | override def isEmpty[A](fa: F[A]): Boolean = false
+ | }
+ -
+ - implicit final def catsUnorderedFoldableInstancesForTuple$arity${`[A0, A(N - 1)]`}
+ - : Traverse[${`(A..N - 1, *)`}] with Reducible[${`(A..N - 1, *)`}]
+ - = instance((fa, G, f) => G.map(f(fa._$arity))(x => fa.copy(_$arity = x)))
|}"""
}
}
diff --git a/project/build.properties b/project/build.properties
index 10fd9eee04..73df629ac1 100644
--- a/project/build.properties
+++ b/project/build.properties
@@ -1 +1 @@
-sbt.version=1.5.5
+sbt.version=1.10.7
diff --git a/project/build.sbt b/project/build.sbt
deleted file mode 100644
index 6b6808a592..0000000000
--- a/project/build.sbt
+++ /dev/null
@@ -1 +0,0 @@
-libraryDependencies += "org.yaml" % "snakeyaml" % "1.29"
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 8b166659e8..9cd55b649e 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -1,27 +1,10 @@
-addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.33")
-addSbtPlugin("com.github.sbt" % "sbt-unidoc" % "0.5.0")
-addSbtPlugin("com.github.sbt" %% "sbt-release" % "1.1.0")
-addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2")
-addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.0.1")
-addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")
-addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.2")
-addSbtPlugin("com.github.tkawachi" % "sbt-doctest" % "0.9.9")
-addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.10")
-addSbtPlugin("com.47deg" % "sbt-microsites" % "1.3.4")
-addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.2.24")
-addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.1.0")
-addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.1.0")
-addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.1")
-addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.1")
-addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.4")
-addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0")
-addSbtPlugin("com.codecommit" % "sbt-github-actions" % "0.13.0")
+val sbtTypelevelVersion = "0.7.6"
+addSbtPlugin("org.typelevel" % "sbt-typelevel" % sbtTypelevelVersion)
+addSbtPlugin("org.typelevel" % "sbt-typelevel-site" % sbtTypelevelVersion)
+addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")
+addSbtPlugin("io.github.sbt-doctest" % "sbt-doctest" % "0.11.1")
+addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.17.0")
+addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.6")
+addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.13.1")
-/* Temporarily disabling sbt-hydra, see #2870.
-resolvers += Resolver.url(
- "Triplequote Plugins Releases",
- url("https://repo.triplequote.com/artifactory/sbt-plugins-release/")
-)(Resolver.ivyStylePatterns)
-
-addSbtPlugin("com.triplequote" % "sbt-hydra" % "2.1.5")
- */
+libraryDependencySchemes += "com.lihaoyi" %% "geny" % VersionScheme.Always
diff --git a/scalafix/project/build.properties b/scalafix/project/build.properties
index 10fd9eee04..73df629ac1 100644
--- a/scalafix/project/build.properties
+++ b/scalafix/project/build.properties
@@ -1 +1 @@
-sbt.version=1.5.5
+sbt.version=1.10.7
diff --git a/shell.nix b/shell.nix
index 820994e357..44595546a4 100644
--- a/shell.nix
+++ b/shell.nix
@@ -1,13 +1,13 @@
let
# use a pinned version of nixpkgs for reproducability
- nixpkgs-version = "21.05";
+ nixpkgs-version = "21.11";
pkgs = import (builtins.fetchTarball {
# Descriptive name to make the store path easier to identify
name = "nixpkgs-${nixpkgs-version}";
url = "https://github.com/nixos/nixpkgs/archive/${nixpkgs-version}.tar.gz";
# Hash obtained using `nix-prefetch-url --unpack `
- sha256 = "1ckzhh24mgz6jd1xhfgx0i9mijk6xjqxwsshnvq789xsavrmsc36";
+ sha256 = "162dywda2dvfj1248afxc45kcrg83appjd0nmdb541hl7rnncf02";
}) {};
in
with pkgs;
diff --git a/testkit/src/main/scala/cats/tests/Helpers.scala b/testkit/src/main/scala/cats/tests/Helpers.scala
index 5ad1be59c3..e47f1e55c0 100644
--- a/testkit/src/main/scala/cats/tests/Helpers.scala
+++ b/testkit/src/main/scala/cats/tests/Helpers.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.kernel._
diff --git a/testkit/src/main/scala/cats/tests/ListWrapper.scala b/testkit/src/main/scala/cats/tests/ListWrapper.scala
index 8b8075ebea..afb6db3e99 100644
--- a/testkit/src/main/scala/cats/tests/ListWrapper.scala
+++ b/testkit/src/main/scala/cats/tests/ListWrapper.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats
package tests
diff --git a/tests/js/src/test/scala/cats/js/instances/future.scala b/tests/js/src/test/scala/cats/js/instances/future.scala
new file mode 100644
index 0000000000..4b11581c8c
--- /dev/null
+++ b/tests/js/src/test/scala/cats/js/instances/future.scala
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats
+package js
+package instances
+
+import scala.concurrent.Future
+import scala.concurrent.{ExecutionContext => E}
+import scala.concurrent.duration.FiniteDuration
+
+import cats.instances.FutureCoflatMap
+import cats.syntax.all._
+
+object future extends FutureInstances0
+
+object Await {
+ def result[A](f: Future[A], atMost: FiniteDuration): A =
+ f.value match {
+ case Some(v) => v.get
+ case None => throw new IllegalStateException()
+ }
+}
+
+sealed private[instances] trait FutureInstances0 extends FutureInstances1 {
+ def futureComonad(atMost: FiniteDuration)(implicit ec: E): Comonad[Future] =
+ new FutureCoflatMap with Comonad[Future] {
+ def extract[A](x: Future[A]): A =
+ Await.result(x, atMost)
+ }
+
+ def futureOrder[A: Order](atMost: FiniteDuration)(implicit ec: E): Order[Future[A]] =
+ (x, y) => Await.result(x.zip(y).map { case (x, y) => x.compare(y) }, atMost)
+}
+
+sealed private[instances] trait FutureInstances1 extends FutureInstances2 {
+ def futurePartialOrder[A: PartialOrder](atMost: FiniteDuration)(implicit ec: E): PartialOrder[Future[A]] =
+ (x, y) => Await.result(x.zip(y).map { case (x, y) => x.partialCompare(y) }, atMost)
+}
+
+sealed private[instances] trait FutureInstances2 {
+ def futureEq[A: Eq](atMost: FiniteDuration)(implicit ec: E): Eq[Future[A]] =
+ (x, y) => Await.result(x.zip(y).map { case (x, y) => x === y }, atMost)
+}
diff --git a/js/src/test/scala/cats/tests/FutureTests.scala b/tests/js/src/test/scala/cats/tests/FutureTests.scala
similarity index 63%
rename from js/src/test/scala/cats/tests/FutureTests.scala
rename to tests/js/src/test/scala/cats/tests/FutureTests.scala
index 167e690848..de67ca9e70 100644
--- a/js/src/test/scala/cats/tests/FutureTests.scala
+++ b/tests/js/src/test/scala/cats/tests/FutureTests.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.js.tests
import cats.Comonad
@@ -34,13 +55,10 @@ class FutureTests extends CatsSuite {
def futureEither[A](f: Future[A]): Future[Either[Throwable, A]] =
f.map(Either.right[Throwable, A]).recover { case t => Either.left(t) }
- implicit def eqfa[A: Eq]: Eq[Future[A]] =
- new Eq[Future[A]] {
- def eqv(fx: Future[A], fy: Future[A]): Boolean = {
- val fz = futureEither(fx).zip(futureEither(fy))
- Await.result(fz.map { case (tx, ty) => tx === ty }, timeout)
- }
- }
+ implicit def eqfa[A: Eq]: Eq[Future[A]] = { (fx, fy) =>
+ val fz = futureEither(fx).zip(futureEither(fy))
+ Await.result(fz.map { case (tx, ty) => tx === ty }, timeout)
+ }
implicit val throwableEq: Eq[Throwable] =
Eq.by[Throwable, String](_.toString)
diff --git a/jvm/src/test/scala/cats/tests/FutureSuite.scala b/tests/jvm-native/src/test/scala/cats/tests/FutureSuite.scala
similarity index 56%
rename from jvm/src/test/scala/cats/tests/FutureSuite.scala
rename to tests/jvm-native/src/test/scala/cats/tests/FutureSuite.scala
index 3d4acf7f0f..cf44c00110 100644
--- a/jvm/src/test/scala/cats/tests/FutureSuite.scala
+++ b/tests/jvm-native/src/test/scala/cats/tests/FutureSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.jvm.tests
import cats.kernel.{Eq, Semigroup}
@@ -19,13 +40,10 @@ class FutureSuite extends CatsSuite {
def futureEither[A](f: Future[A]): Future[Either[Throwable, A]] =
f.map(Either.right[Throwable, A]).recover { case t => Either.left(t) }
- implicit def eqfa[A: Eq]: Eq[Future[A]] =
- new Eq[Future[A]] {
- def eqv(fx: Future[A], fy: Future[A]): Boolean = {
- val fz = futureEither(fx).zip(futureEither(fy))
- Await.result(fz.map { case (tx, ty) => tx === ty }, timeout)
- }
- }
+ implicit def eqfa[A: Eq]: Eq[Future[A]] = { (fx, fy) =>
+ val fz = futureEither(fx).zip(futureEither(fy))
+ Await.result(fz.map { case (tx, ty) => tx === ty }, timeout)
+ }
implicit def cogen[A: Cogen]: Cogen[Future[A]] =
Cogen[Future[A]] { (seed: Seed, t: Future[A]) =>
diff --git a/tests/src/test/scala-2.12/cats/tests/NonEmptyStreamSuite.scala b/tests/shared/src/test/scala-2.12/cats/tests/NonEmptyStreamSuite.scala
similarity index 86%
rename from tests/src/test/scala-2.12/cats/tests/NonEmptyStreamSuite.scala
rename to tests/shared/src/test/scala-2.12/cats/tests/NonEmptyStreamSuite.scala
index 6b72c700a2..cece2a83dd 100644
--- a/tests/src/test/scala-2.12/cats/tests/NonEmptyStreamSuite.scala
+++ b/tests/shared/src/test/scala-2.12/cats/tests/NonEmptyStreamSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Comonad, Eval, Functor, Monad, NonEmptyTraverse, Now, Reducible, SemigroupK, Show}
diff --git a/tests/src/test/scala-2.12/cats/tests/ScalaVersionSpecific.scala b/tests/shared/src/test/scala-2.12/cats/tests/ScalaVersionSpecific.scala
similarity index 62%
rename from tests/src/test/scala-2.12/cats/tests/ScalaVersionSpecific.scala
rename to tests/shared/src/test/scala-2.12/cats/tests/ScalaVersionSpecific.scala
index 072a07f33a..fa4e29a511 100644
--- a/tests/src/test/scala-2.12/cats/tests/ScalaVersionSpecific.scala
+++ b/tests/shared/src/test/scala-2.12/cats/tests/ScalaVersionSpecific.scala
@@ -1,11 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
+import cats.kernel.{Eq, Order}
import cats.laws.discipline.{ExhaustiveCheck, MiniInt}
import cats.laws.discipline.MiniInt._
import cats.laws.discipline.eq._
-import cats.laws.discipline.DeprecatedEqInstances
-import cats.kernel.{Eq, Order}
-import org.scalacheck.Arbitrary
trait ScalaVersionSpecificFoldableSuite
trait ScalaVersionSpecificParallelSuite
@@ -14,7 +33,7 @@ trait ScalaVersionSpecificTraverseSuite
trait ScalaVersionSpecificAlgebraInvariantSuite {
// This version-specific instance is required since 2.12 and below do not have parseString on the Numeric class
- protected val integralForMiniInt: Integral[MiniInt] = new Integral[MiniInt] {
+ protected trait MiniIntNumeric extends Numeric[MiniInt] {
def compare(x: MiniInt, y: MiniInt): Int = Order[MiniInt].compare(x, y)
def plus(x: MiniInt, y: MiniInt): MiniInt = x + y
def minus(x: MiniInt, y: MiniInt): MiniInt = x + (-y)
@@ -25,8 +44,6 @@ trait ScalaVersionSpecificAlgebraInvariantSuite {
def toLong(x: MiniInt): Long = x.toInt.toLong
def toFloat(x: MiniInt): Float = x.toInt.toFloat
def toDouble(x: MiniInt): Double = x.toInt.toDouble
- def quot(x: MiniInt, y: MiniInt): MiniInt = MiniInt.unsafeFromInt(x.toInt / y.toInt)
- def rem(x: MiniInt, y: MiniInt): MiniInt = MiniInt.unsafeFromInt(x.toInt % y.toInt)
}
// This version-specific instance is required since 2.12 and below do not have parseString on the Numeric class
@@ -54,23 +71,4 @@ trait ScalaVersionSpecificAlgebraInvariantSuite {
)
}
- // This version-specific instance is required since 2.12 and below do not have parseString on the Numeric class
- implicit protected def eqFractional[A: Eq: Arbitrary]: Eq[Fractional[A]] = {
- import DeprecatedEqInstances.catsLawsEqForFn1
-
- Eq.by { fractional =>
- (
- fractional.compare _,
- fractional.plus _,
- fractional.minus _,
- fractional.times _,
- fractional.negate _,
- fractional.fromInt _,
- fractional.toInt _,
- fractional.toLong _,
- fractional.toFloat _,
- fractional.toDouble _
- )
- }
- }
}
diff --git a/tests/shared/src/test/scala-2.12/cats/tests/compat/ScalaVersionSpecificSyntax.scala b/tests/shared/src/test/scala-2.12/cats/tests/compat/ScalaVersionSpecificSyntax.scala
new file mode 100644
index 0000000000..801eb5725b
--- /dev/null
+++ b/tests/shared/src/test/scala-2.12/cats/tests/compat/ScalaVersionSpecificSyntax.scala
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests.compat
+
+import scala.collection.immutable.Seq
+
+private[tests] trait ScalaVersionSpecificSyntax {
+ implicit final private[tests] def catsTestsCompatSeqOps[C[a] <: Seq[a], A](self: C[A]) = new SeqOps[C, A](self)
+}
diff --git a/tests/shared/src/test/scala-2.12/cats/tests/compat/SeqOps.scala b/tests/shared/src/test/scala-2.12/cats/tests/compat/SeqOps.scala
new file mode 100644
index 0000000000..c77fe2386f
--- /dev/null
+++ b/tests/shared/src/test/scala-2.12/cats/tests/compat/SeqOps.scala
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* This file is derived in part from https://github.com/scala/scala/blob/v2.13.8/src/library/scala/collection/immutable/StrictOptimizedSeqOps.scala
+ * Modified by Typelevel for redistribution in Cats.
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ * Scala
+ * Copyright (c) 2002-2022 EPFL
+ * Copyright (c) 2011-2022 Lightbend, Inc.
+ *
+ * Scala includes software developed at
+ * LAMP/EPFL (https://lamp.epfl.ch/) and
+ * Lightbend, Inc. (https://www.lightbend.com/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package cats.tests.compat
+
+import scala.collection.generic.CanBuildFrom
+import scala.collection.immutable.Seq
+import scala.collection.mutable
+
+final private[tests] class SeqOps[C[a] <: Seq[a], A] private[compat] (private val self: C[A]) extends AnyVal {
+
+ // Scala v2.12.x does not have `distinctBy` implemented.
+ // Therefore this implementation is copied (and adapted) from Scala Library v2.13.8 sources:
+ // https://github.com/scala/scala/blob/v2.13.8/src/library/scala/collection/immutable/StrictOptimizedSeqOps.scala#L26-L39
+ def distinctBy[B](f: A => B)(implicit cbf: CanBuildFrom[C[A], A, C[A]]): C[A] = {
+ if (self.lengthCompare(1) <= 0) self
+ else {
+ val builder = cbf()
+ val seen = mutable.HashSet.empty[B]
+ val it = self.iterator
+ var different = false
+ while (it.hasNext) {
+ val next = it.next()
+ if (seen.add(f(next))) builder += next else different = true
+ }
+ if (different) builder.result() else self
+ }
+ }
+}
diff --git a/tests/src/test/scala-2.13+/cats/tests/ArraySeqSuite.scala b/tests/shared/src/test/scala-2.13+/cats/tests/ArraySeqSuite.scala
similarity index 68%
rename from tests/src/test/scala-2.13+/cats/tests/ArraySeqSuite.scala
rename to tests/shared/src/test/scala-2.13+/cats/tests/ArraySeqSuite.scala
index 1b2e8ba687..2d1b3296de 100644
--- a/tests/src/test/scala-2.13+/cats/tests/ArraySeqSuite.scala
+++ b/tests/shared/src/test/scala-2.13+/cats/tests/ArraySeqSuite.scala
@@ -1,6 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Align, Alternative, CoflatMap, Monad, MonoidK, Traverse, TraverseFilter}
+import cats.{Align, Alternative, CoflatMap, Eval, Monad, MonoidK, Traverse, TraverseFilter}
import cats.kernel.{Eq, Hash, Monoid, Order, PartialOrder}
import cats.kernel.laws.discipline.{EqTests, HashTests, MonoidTests, OrderTests, PartialOrderTests}
import cats.laws.discipline.{
@@ -31,7 +52,9 @@ class ArraySeqSuite extends CatsSuite {
checkAll("ArraySeq[Int]", AlternativeTests[ArraySeq].alternative[Int, Int, Int])
checkAll("Alternative[ArraySeq]", SerializableTests.serializable(Alternative[ArraySeq]))
+ // Traverse behaviour discriminates on the Runtime type of the Applicative
checkAll("ArraySeq[Int] with Option", TraverseTests[ArraySeq].traverse[Int, Int, Int, Set[Int], Option, Option])
+ checkAll("ArraySeq[Int] with Eval", TraverseTests[ArraySeq].traverse[Int, Int, Int, Set[Int], Eval, Eval])
checkAll("Traverse[ArraySeq]", SerializableTests.serializable(Traverse[ArraySeq]))
checkAll("ArraySeq[Int]", MonadTests[ArraySeq].monad[Int, Int, Int])
diff --git a/tests/shared/src/test/scala-2.13+/cats/tests/FoldableLazyListSuite.scala b/tests/shared/src/test/scala-2.13+/cats/tests/FoldableLazyListSuite.scala
new file mode 100644
index 0000000000..285b933fe1
--- /dev/null
+++ b/tests/shared/src/test/scala-2.13+/cats/tests/FoldableLazyListSuite.scala
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+class FoldableLazyListSuite extends FoldableSuite[LazyList]("lazyList") {
+ def iterator[T](list: LazyList[T]): Iterator[T] = list.iterator
+}
diff --git a/tests/src/test/scala-2.13+/cats/tests/LazyListSuite.scala b/tests/shared/src/test/scala-2.13+/cats/tests/LazyListSuite.scala
similarity index 75%
rename from tests/src/test/scala-2.13+/cats/tests/LazyListSuite.scala
rename to tests/shared/src/test/scala-2.13+/cats/tests/LazyListSuite.scala
index 6a5365ab8a..6f33e857eb 100644
--- a/tests/src/test/scala-2.13+/cats/tests/LazyListSuite.scala
+++ b/tests/shared/src/test/scala-2.13+/cats/tests/LazyListSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Align, Alternative, CoflatMap, Monad, Semigroupal, Traverse, TraverseFilter}
diff --git a/tests/src/test/scala-2.13+/cats/tests/NonEmptyLazyListSuite.scala b/tests/shared/src/test/scala-2.13+/cats/tests/NonEmptyLazyListSuite.scala
similarity index 77%
rename from tests/src/test/scala-2.13+/cats/tests/NonEmptyLazyListSuite.scala
rename to tests/shared/src/test/scala-2.13+/cats/tests/NonEmptyLazyListSuite.scala
index 40c1dad831..6043bb870e 100644
--- a/tests/src/test/scala-2.13+/cats/tests/NonEmptyLazyListSuite.scala
+++ b/tests/shared/src/test/scala-2.13+/cats/tests/NonEmptyLazyListSuite.scala
@@ -1,23 +1,41 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Align, Bimonad, SemigroupK, Show, Traverse}
-import cats.data.{NonEmptyLazyList, NonEmptyLazyListOps, NonEmptyVector}
-import cats.kernel.{Eq, Hash, Order, PartialOrder, Semigroup}
-import cats.kernel.laws.discipline.{EqTests, HashTests, OrderTests, PartialOrderTests, SemigroupTests}
-import cats.laws.discipline.{
- AlignTests,
- BimonadTests,
- NonEmptyTraverseTests,
- SemigroupKTests,
- SerializableTests,
- ShortCircuitingTests
-}
+import cats._
+import cats.data.NonEmptyLazyList
+import cats.data.NonEmptyLazyListOps
+import cats.data.NonEmptyVector
+import cats.kernel.laws.discipline.EqTests
+import cats.kernel.laws.discipline.HashTests
+import cats.kernel.laws.discipline.OrderTests
+import cats.kernel.laws.discipline.PartialOrderTests
+import cats.kernel.laws.discipline.SemigroupTests
+import cats.kernel.laws.discipline.SerializableTests
+import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
import cats.syntax.either._
-import cats.syntax.foldable._
import cats.syntax.eq._
-import cats.Reducible
-import cats.Eval
+import cats.syntax.foldable._
import org.scalacheck.Prop._
class NonEmptyLazyListSuite extends NonEmptyCollectionSuite[LazyList, NonEmptyLazyList, NonEmptyLazyListOps] {
@@ -31,8 +49,10 @@ class NonEmptyLazyListSuite extends NonEmptyCollectionSuite[LazyList, NonEmptyLa
checkAll(s"NonEmptyLazyList[Int]", HashTests[NonEmptyLazyList[Int]].hash)
checkAll(s"Hash[NonEmptyLazyList[Int]]", SerializableTests.serializable(Hash[NonEmptyLazyList[Int]]))
- checkAll("NonEmptyLazyList[Int]", SemigroupKTests[NonEmptyLazyList].semigroupK[Int])
- checkAll("SemigroupK[NonEmptyLazyList]", SerializableTests.serializable(SemigroupK[NonEmptyLazyList]))
+ checkAll("NonEmptyLazyList[Int]", NonEmptyAlternativeTests[NonEmptyLazyList].nonEmptyAlternative[Int, Int, Int])
+ checkAll("NonEmptyAlternative[NonEmptyLazyList]",
+ SerializableTests.serializable(NonEmptyAlternative[NonEmptyLazyList])
+ )
checkAll("NonEmptyLazyList[Int] with Option",
NonEmptyTraverseTests[NonEmptyLazyList].nonEmptyTraverse[Option, Int, Int, Int, Int, Option, Option]
@@ -155,6 +175,12 @@ class NonEmptyLazyListSuite extends NonEmptyCollectionSuite[LazyList, NonEmptyLa
}
}
+ test("NonEmptyLazyList#distinctBy is consistent with List#distinctBy") {
+ forAll { (ci: NonEmptyLazyList[Int], f: Int => String) =>
+ assert(ci.distinctBy(f).toList === (ci.toList.distinctBy(f)))
+ }
+ }
+
test("NonEmptyLazyList#distinct is consistent with List#distinct") {
forAll { (ci: NonEmptyLazyList[Int]) =>
assert(ci.distinct.toList === (ci.toList.distinct))
diff --git a/tests/src/test/scala-2.13+/cats/tests/ScalaVersionSpecific.scala b/tests/shared/src/test/scala-2.13+/cats/tests/ScalaVersionSpecific.scala
similarity index 78%
rename from tests/src/test/scala-2.13+/cats/tests/ScalaVersionSpecific.scala
rename to tests/shared/src/test/scala-2.13+/cats/tests/ScalaVersionSpecific.scala
index 0fbe1aea99..0aa3bdd8fc 100644
--- a/tests/src/test/scala-2.13+/cats/tests/ScalaVersionSpecific.scala
+++ b/tests/shared/src/test/scala-2.13+/cats/tests/ScalaVersionSpecific.scala
@@ -1,28 +1,48 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Eval, Foldable, Id, Now}
+import cats._
import cats.data.NonEmptyLazyList
-import cats.laws.discipline.{ExhaustiveCheck, MiniInt, NonEmptyParallelTests, ParallelTests}
+import cats.laws.discipline.ExhaustiveCheck
+import cats.laws.discipline.MiniInt
+import cats.laws.discipline.NonEmptyParallelTests
+import cats.laws.discipline.ParallelTests
import cats.laws.discipline.arbitrary._
-import cats.laws.discipline.DeprecatedEqInstances
-import cats.syntax.either._
-import cats.syntax.foldable._
-import cats.syntax.parallel._
-import cats.syntax.traverse._
-import cats.syntax.eq._
-import org.scalacheck.Prop._
-import cats.kernel.{Eq, Order}
import cats.laws.discipline.eq._
-import org.scalacheck.Arbitrary
+import cats.syntax.all._
+import org.scalacheck.Prop._
trait ScalaVersionSpecificFoldableSuite { self: FoldableSuiteAdditional =>
- test("Foldable[LazyList].foldM stack safety") {
- checkMonadicFoldsStackSafety[LazyList](_.to(LazyList))
- }
+ test("Foldable[LazyList] monadic folds stack safety")(checkMonadicFoldsStackSafety(_.to(LazyList)))
+ test("Foldable[LazyList].slidingN stack safety")(checkSlidingNStackSafety(_.to(LazyList)))
- test("Foldable[NonEmptyLazyList].foldM/existsM/forallM/findM/collectFirstSomeM stack safety") {
- checkMonadicFoldsStackSafety[NonEmptyLazyList](xs => NonEmptyLazyList(xs.head, xs.tail: _*))
- }
+ test("Foldable[NonEmptyLazyList] monadic folds stack safety")(
+ checkMonadicFoldsStackSafety(xs => NonEmptyLazyList(xs.head, xs.tail: _*))
+ )
+
+ test("Foldable[NonEmptyLazyList].slidingN stack safety")(
+ checkSlidingNStackSafety(xs => NonEmptyLazyList(xs.head, xs.tail: _*))
+ )
private def bombLazyList[A]: A = sys.error("boom")
private val dangerousLazyList = 0 #:: 1 #:: 2 #:: bombLazyList[Int] #:: LazyList.empty
@@ -54,7 +74,7 @@ trait ScalaVersionSpecificFoldableSuite { self: FoldableSuiteAdditional =>
}
test("Foldable[LazyList] laziness of foldM") {
- assert(dangerous.foldM(0)((acc, a) => if (a < 2) Some(acc + a) else None) === None)
+ assert(dangerousLazyList.foldM(0)((acc, a) => if (a < 2) Some(acc + a) else None) === None)
}
def foldableLazyListWithDefaultImpl: Foldable[LazyList] =
@@ -101,6 +121,10 @@ trait ScalaVersionSpecificFoldableSuite { self: FoldableSuiteAdditional =>
assert((1 #:: boomLazyList[Int]).findM[Id](_ > 0) == Some(1))
assert((1 #:: boomLazyList[Int]).collectFirstSomeM[Id, Int](Option.apply) == Some(1))
}
+
+ test("#4244 ambiguous `contains_` syntax") {
+ assertEquals(List("a").map(List("a").contains_), List(true))
+ }
}
trait ScalaVersionSpecificParallelSuite { self: ParallelSuite =>
@@ -155,7 +179,7 @@ trait ScalaVersionSpecificRegressionSuite { self: RegressionSuite =>
// shouldn't have ever evaluated validate(8)
checkAndResetCount(3)
- assert(LazyList(1, 2, 6, 8).traverse_(validate) === (Either.left("6 is greater than 5")))
+ assert(LazyList(1, 2, 6, 8).traverseVoid(validate) === Either.left("6 is greater than 5"))
checkAndResetCount(3)
}
}
@@ -169,7 +193,7 @@ trait ScalaVersionSpecificTraverseSuite { self: TraverseSuiteAdditional =>
trait ScalaVersionSpecificAlgebraInvariantSuite {
// This version-specific instance is required since 2.12 and below do not have parseString on the Numeric class
- protected val integralForMiniInt: Integral[MiniInt] = new Integral[MiniInt] {
+ protected trait MiniIntNumeric extends Numeric[MiniInt] {
def compare(x: MiniInt, y: MiniInt): Int = Order[MiniInt].compare(x, y)
def plus(x: MiniInt, y: MiniInt): MiniInt = x + y
def minus(x: MiniInt, y: MiniInt): MiniInt = x + (-y)
@@ -180,8 +204,6 @@ trait ScalaVersionSpecificAlgebraInvariantSuite {
def toLong(x: MiniInt): Long = x.toInt.toLong
def toFloat(x: MiniInt): Float = x.toInt.toFloat
def toDouble(x: MiniInt): Double = x.toInt.toDouble
- def quot(x: MiniInt, y: MiniInt): MiniInt = MiniInt.unsafeFromInt(x.toInt / y.toInt)
- def rem(x: MiniInt, y: MiniInt): MiniInt = MiniInt.unsafeFromInt(x.toInt % y.toInt)
def parseString(str: String): Option[MiniInt] = Integral[Int].parseString(str).flatMap(MiniInt.fromInt)
}
@@ -216,34 +238,6 @@ trait ScalaVersionSpecificAlgebraInvariantSuite {
)
}
- // This version-specific instance is required since 2.12 and below do not have parseString on the Numeric class
- implicit protected def eqFractional[A: Eq: Arbitrary]: Eq[Fractional[A]] = {
- // This deprecated instance is required since there is not `ExhaustiveCheck` for any types for which a `Fractional`
- // can easily be defined
- import DeprecatedEqInstances.catsLawsEqForFn1
-
- Eq.by { fractional =>
- val parseFloatStrings: Option[Double] => Option[A] = {
- case Some(f) => fractional.parseString(f.toString)
- case None => fractional.parseString("invalid") // Use this to test parsing of non-numeric strings
- }
-
- (
- fractional.compare _,
- fractional.plus _,
- fractional.minus _,
- fractional.times _,
- fractional.negate _,
- fractional.fromInt _,
- fractional.toInt _,
- fractional.toLong _,
- fractional.toFloat _,
- fractional.toDouble _,
- parseFloatStrings
- )
- }
- }
-
}
class TraverseLazyListSuite extends TraverseSuite[LazyList]("LazyList")
diff --git a/tests/shared/src/test/scala-2.13+/cats/tests/compat/ScalaVersionSpecificSyntax.scala b/tests/shared/src/test/scala-2.13+/cats/tests/compat/ScalaVersionSpecificSyntax.scala
new file mode 100644
index 0000000000..90761716a8
--- /dev/null
+++ b/tests/shared/src/test/scala-2.13+/cats/tests/compat/ScalaVersionSpecificSyntax.scala
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests.compat
+
+private[tests] trait ScalaVersionSpecificSyntax {}
diff --git a/tests/src/test/scala-2.x/cats/tests/FunctionKLiftSuite.scala b/tests/shared/src/test/scala-2/cats/tests/FunctionKLiftSuite.scala
similarity index 62%
rename from tests/src/test/scala-2.x/cats/tests/FunctionKLiftSuite.scala
rename to tests/shared/src/test/scala-2/cats/tests/FunctionKLiftSuite.scala
index 26dc277668..04257a3474 100644
--- a/tests/src/test/scala-2.x/cats/tests/FunctionKLiftSuite.scala
+++ b/tests/shared/src/test/scala-2/cats/tests/FunctionKLiftSuite.scala
@@ -1,9 +1,30 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.Applicative
import cats.data.NonEmptyList
import cats.arrow.FunctionK
-import cats.implicits._
+import cats.syntax.all._
import org.scalacheck.Prop._
import cats.laws.discipline.arbitrary._
@@ -51,14 +72,6 @@ class FunctionKLiftSuite extends CatsSuite {
}
}
- test("lift a function directly") {
- def headOption[A](list: List[A]): Option[A] = list.headOption
- val fHeadOption = FunctionK.liftFunction[List, Option](headOption)
- forAll { (a: List[Int]) =>
- assert(fHeadOption(a) === a.headOption)
- }
- }
-
{ // lifting concrete types should fail to compile
def sample[A](option: Option[A]): List[A] = option.toList
assert(compileErrors("FunctionK.lift(sample[String])").nonEmpty)
diff --git a/tests/shared/src/test/scala-3/cats/tests/FunctionKLiftSuite.scala b/tests/shared/src/test/scala-3/cats/tests/FunctionKLiftSuite.scala
new file mode 100644
index 0000000000..da70f8fc87
--- /dev/null
+++ b/tests/shared/src/test/scala-3/cats/tests/FunctionKLiftSuite.scala
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.arrow.FunctionK
+import cats.syntax.all._
+import org.scalacheck.Prop._
+import cats.laws.discipline.arbitrary._
+
+class FunctionKLiftSuite extends CatsSuite {
+
+ test("lift a polymorphic function directly") {
+ val fHeadOption = FunctionK.lift[List, Option]([X] => (_: List[X]).headOption)
+ forAll { (a: List[Int]) =>
+ assert(fHeadOption(a) === a.headOption)
+ }
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala b/tests/shared/src/test/scala/cats/tests/AlgebraInvariantSuite.scala
similarity index 83%
rename from tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala
rename to tests/shared/src/test/scala/cats/tests/AlgebraInvariantSuite.scala
index f86be7ca25..fa8fabace7 100644
--- a/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/AlgebraInvariantSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{CommutativeApplicative, CommutativeApply, Invariant, InvariantMonoidal}
@@ -51,11 +72,6 @@ class AlgebraInvariantSuite extends CatsSuite with ScalaVersionSpecificAlgebraIn
def combine(x: Option[A], y: Option[A]): Option[A] = y
}
- private val boundedSemilatticeMiniInt: BoundedSemilattice[MiniInt] = new BoundedSemilattice[MiniInt] {
- def empty: MiniInt = MiniInt.zero
- def combine(x: MiniInt, y: MiniInt): MiniInt = x | y
- }
-
private val genBoundedSemilatticeMiniInt: Gen[BoundedSemilattice[MiniInt]] =
Gen.const(miniIntOr)
@@ -158,11 +174,13 @@ class AlgebraInvariantSuite extends CatsSuite with ScalaVersionSpecificAlgebraIn
implicit private val arbCommutativeGroupInt: Arbitrary[CommutativeGroup[Int]] =
Arbitrary(genCommutativeGroupInt)
+ protected val integralForMiniInt: Numeric[MiniInt] & Integral[MiniInt] = new MiniIntNumeric with Integral[MiniInt] {
+ def quot(x: MiniInt, y: MiniInt): MiniInt = MiniInt.unsafeFromInt(x.toInt / y.toInt)
+ def rem(x: MiniInt, y: MiniInt): MiniInt = MiniInt.unsafeFromInt(x.toInt % y.toInt)
+ }
+
implicit private val arbNumericMiniInt: Arbitrary[Numeric[MiniInt]] = Arbitrary(Gen.const(integralForMiniInt))
implicit private val arbIntegralMiniInt: Arbitrary[Integral[MiniInt]] = Arbitrary(Gen.const(integralForMiniInt))
- implicit private val arbFractionalFloat: Arbitrary[Fractional[Float]] = Arbitrary(
- Gen.const(implicitly[Fractional[Float]])
- )
implicit protected def eqIntegral[A: Eq: ExhaustiveCheck]: Eq[Integral[A]] = {
def makeDivisionOpSafe(unsafeF: (A, A) => A): (A, A) => Option[A] =
@@ -188,6 +206,14 @@ class AlgebraInvariantSuite extends CatsSuite with ScalaVersionSpecificAlgebraIn
}
}
+ implicit protected def eqFractional[A: Eq: ExhaustiveCheck]: Eq[Fractional[A]] =
+ Eq.by { fractional =>
+ (
+ fractional: Numeric[A],
+ fractional.div(_, _)
+ )
+ }
+
checkAll("InvariantMonoidal[Semigroup]", SemigroupTests[Int](InvariantMonoidal[Semigroup].point(0)).semigroup)
checkAll("InvariantMonoidal[CommutativeSemigroup]",
CommutativeSemigroupTests[Int](InvariantMonoidal[CommutativeSemigroup].point(0)).commutativeSemigroup
@@ -197,10 +223,6 @@ class AlgebraInvariantSuite extends CatsSuite with ScalaVersionSpecificAlgebraIn
InvariantSemigroupalTests[Monoid].invariantSemigroupal[Option[MiniInt], Option[Boolean], Option[Boolean]]
)
- checkAll("Invariant[Numeric]", InvariantTests[Numeric].invariant[MiniInt, Boolean, Boolean])
- checkAll("Invariant[Integral]", InvariantTests[Integral].invariant[MiniInt, Boolean, Boolean])
- checkAll("Invariant[Fractional]", InvariantTests[Fractional].invariant[Float, Boolean, Boolean])
-
{
val S: Semigroup[Int] = Semigroup[Int].imap(identity)(identity)
checkAll("Semigroup[Int]", SemigroupTests[Int](S).semigroup)
@@ -289,6 +311,25 @@ class AlgebraInvariantSuite extends CatsSuite with ScalaVersionSpecificAlgebraIn
checkAll("Invariant[CommutativeGroup]", InvariantTests[CommutativeGroup].invariant[MiniInt, Boolean, Boolean])
checkAll("Invariant[CommutativeGroup]", SerializableTests.serializable(Invariant[CommutativeGroup]))
+ checkAll("Invariant[Numeric]", InvariantTests[Numeric].invariant[MiniInt, Boolean, Boolean])
+ checkAll("Invariant[Integral]", InvariantTests[Integral].invariant[MiniInt, Boolean, Boolean])
+
+ {
+ // This is a spurious instance since MiniInt is not a Fractional data type. But we use it since we don't have a
+ // Fractional type for which ExhaustiveCheck is also implemented. See https://github.com/typelevel/cats/pull/4033
+ val fractionalForMiniInt: Fractional[MiniInt] = new MiniIntNumeric with Fractional[MiniInt] {
+ def div(x: MiniInt, y: MiniInt): MiniInt =
+ if (y == MiniInt.zero) {
+ MiniInt.maxValue
+ } else {
+ x / y
+ }
+ }
+ implicit val arbFractionalMiniInt: Arbitrary[Fractional[MiniInt]] = Arbitrary(Gen.const(fractionalForMiniInt))
+
+ checkAll("Invariant[Fractional]", InvariantTests[Fractional].invariant[MiniInt, Boolean, Boolean])
+ }
+
checkAll("InvariantMonoidal[Semigroup]",
InvariantMonoidalTests[Semigroup].invariantMonoidal[Option[MiniInt], Option[Boolean], Option[Boolean]]
)
diff --git a/tests/shared/src/test/scala/cats/tests/AlignSuite.scala b/tests/shared/src/test/scala/cats/tests/AlignSuite.scala
new file mode 100644
index 0000000000..eac3c3a2d5
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/AlignSuite.scala
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Align
+import cats.kernel.laws.discipline.SemigroupTests
+
+class AlignSuite extends CatsSuite {
+ {
+ val optionSemigroup = Align.semigroup[Option, Int]
+ checkAll("Align[Option].semigroup", SemigroupTests[Option[Int]](optionSemigroup).semigroup)
+
+ val listSemigroup = Align.semigroup[List, String]
+ checkAll("Align[List].semigroup", SemigroupTests[List[String]](listSemigroup).semigroup)
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/AlternativeSuite.scala b/tests/shared/src/test/scala/cats/tests/AlternativeSuite.scala
similarity index 71%
rename from tests/src/test/scala/cats/tests/AlternativeSuite.scala
rename to tests/shared/src/test/scala/cats/tests/AlternativeSuite.scala
index d715c7f5f7..ec3858045b 100644
--- a/tests/src/test/scala/cats/tests/AlternativeSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/AlternativeSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.Alternative
diff --git a/tests/src/test/scala/cats/tests/AndThenSuite.scala b/tests/shared/src/test/scala/cats/tests/AndThenSuite.scala
similarity index 84%
rename from tests/src/test/scala/cats/tests/AndThenSuite.scala
rename to tests/shared/src/test/scala/cats/tests/AndThenSuite.scala
index b5d5f3dee4..e833e69c58 100644
--- a/tests/src/test/scala/cats/tests/AndThenSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/AndThenSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Contravariant, ContravariantMonoidal, Monad, Semigroupal}
@@ -67,7 +88,7 @@ class AndThenSuite extends CatsSuite with ScalaCheckSuite {
val fs = (0 until count).map(_ => (i: Int) => i + 1)
val result = fs.foldLeft(AndThen((x: Int) => x))(_.andThen(_))(42)
- assertEquals(result, (count + 42))
+ assertEquals(result, count + 42)
}
test("compose is stack safe") {
@@ -75,7 +96,7 @@ class AndThenSuite extends CatsSuite with ScalaCheckSuite {
val fs = (0 until count).map(_ => (i: Int) => i + 1)
val result = fs.foldLeft(AndThen((x: Int) => x))(_.compose(_))(42)
- assertEquals(result, (count + 42))
+ assertEquals(result, count + 42)
}
test("Function1 andThen is stack safe") {
@@ -160,7 +181,7 @@ class AndThenSuite extends CatsSuite with ScalaCheckSuite {
forAll(genLeft[Int]) { at =>
val notInit = AndThen.isRightAssociated(at)
val done = AndThen.isRightAssociated(AndThen.toRightAssociated(at))
- (!notInit && done)
+ !notInit && done
} &&
// check that right associating doesn't change the function value
forAll(genAndThen[Int], Gen.choose(Int.MinValue, Int.MaxValue)) { (at, i) =>
diff --git a/tests/src/test/scala/cats/tests/ApplicativeErrorSuite.scala b/tests/shared/src/test/scala/cats/tests/ApplicativeErrorSuite.scala
similarity index 77%
rename from tests/src/test/scala/cats/tests/ApplicativeErrorSuite.scala
rename to tests/shared/src/test/scala/cats/tests/ApplicativeErrorSuite.scala
index 9eb7acc038..631d72b685 100644
--- a/tests/src/test/scala/cats/tests/ApplicativeErrorSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/ApplicativeErrorSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.ApplicativeError
diff --git a/tests/src/test/scala/cats/tests/ApplicativeSuite.scala b/tests/shared/src/test/scala/cats/tests/ApplicativeSuite.scala
similarity index 60%
rename from tests/src/test/scala/cats/tests/ApplicativeSuite.scala
rename to tests/shared/src/test/scala/cats/tests/ApplicativeSuite.scala
index bca6055deb..9af965b1f3 100644
--- a/tests/src/test/scala/cats/tests/ApplicativeSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/ApplicativeSuite.scala
@@ -1,13 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Align, Applicative, Apply, CoflatMap}
-import cats.data.{Const, Validated}
+import cats.data.{Const, State, Validated}
import cats.kernel.Monoid
import cats.kernel.laws.discipline.{MonoidTests, SemigroupTests}
import cats.laws.discipline.arbitrary._
import cats.laws.discipline.{AlignTests, CoflatMapTests}
import cats.syntax.applicative._
import cats.syntax.eq._
+import cats.syntax.functor._
+import cats.{Align, Applicative, Apply, CoflatMap}
import org.scalacheck.Prop._
class ApplicativeSuite extends CatsSuite {
@@ -18,6 +40,20 @@ class ApplicativeSuite extends CatsSuite {
assert(fa.replicateA(5) === (Some(List(1, 1, 1, 1, 1))))
}
+ test("replicateA_ executes the Applicative action 'fa' 'n' times") {
+ val A = Applicative[Option]
+ val fa = A.pure(0)
+ val increment: State[Int, Int] = State { i => (i + 1, i) }
+ val aUnit = A.unit
+
+ for (num <- 0 to 10) {
+ assertEquals(fa.replicateA_(num), aUnit)
+ assertEquals(increment.replicateA_(num).runS(0).value, num)
+ assertEquals(increment.replicateA_(num).run(0).value, ((num, ())))
+ assertEquals(increment.replicateA_(num).run(0).value, increment.replicateA(num).void.run(0).value)
+ }
+ }
+
test("whenA return given argument when cond is true") {
forAll { (l: List[Int]) =>
assert(l.whenA(true) === (List.fill(l.length)(())))
@@ -42,6 +78,16 @@ class ApplicativeSuite extends CatsSuite {
}
}
+ test("by-name ops are lazy") {
+ var i = 0
+ Option(i += 1).whenA(false)
+ assertEquals(i, 0)
+
+ var j = 0
+ Option(j += 1).unlessA(true)
+ assertEquals(j, 0)
+ }
+
{
implicit val optionMonoid: Monoid[Option[Int]] = Applicative.monoid[Option, Int]
checkAll("Applicative[Option].monoid", MonoidTests[Option[Int]](optionMonoid).monoid)
diff --git a/tests/src/test/scala/cats/tests/AsSuite.scala b/tests/shared/src/test/scala/cats/tests/AsSuite.scala
similarity index 71%
rename from tests/src/test/scala/cats/tests/AsSuite.scala
rename to tests/shared/src/test/scala/cats/tests/AsSuite.scala
index a2820cbfbe..533f6242fe 100644
--- a/tests/src/test/scala/cats/tests/AsSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/AsSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.kernel.Eq
@@ -82,12 +103,12 @@ class AsSuite extends CatsSuite {
test("we can lift subtyping to covariant type constructors") {
val cAsA: Bottom As Top = implicitly
val co: List[Bottom] As List[Top] = As.co(cAsA)
- val co2: ((Bottom, String) As (Top, String)) = As.co2(cAsA)
- val co2_2: ((String, Bottom) As (String, Top)) = As.co2_2(cAsA)
- val co3: ((Bottom, Unit, Unit) As (Top, Unit, Unit)) = As.co3(cAsA)
- val co3_2: ((Unit, Bottom, Unit) As (Unit, Top, Unit)) = As.co3_2(cAsA)
- val co3_3: ((Unit, Unit, Bottom) As (Unit, Unit, Top)) = As.co3_3(cAsA)
- val lift2: ((Bottom, String) As (Top, Any)) = As.lift2(cAsA, implicitly)
+ val co2: (Bottom, String) As (Top, String) = As.co2(cAsA)
+ val co2_2: (String, Bottom) As (String, Top) = As.co2_2(cAsA)
+ val co3: (Bottom, Unit, Unit) As (Top, Unit, Unit) = As.co3(cAsA)
+ val co3_2: (Unit, Bottom, Unit) As (Unit, Top, Unit) = As.co3_2(cAsA)
+ val co3_3: (Unit, Unit, Bottom) As (Unit, Unit, Top) = As.co3_3(cAsA)
+ val lift2: (Bottom, String) As (Top, Any) = As.lift2(cAsA, implicitly)
}
test("we can lift subtyping to contravariant type constructors") {
@@ -98,7 +119,7 @@ class AsSuite extends CatsSuite {
type EatF23[B, -A, C] = A => (B, C)
type EatF33[B, C, -A] = A => (B, C)
- val cAsA: (Bottom As Top) = implicitly
+ val cAsA: Bottom As Top = implicitly
val contra: Eat[Top] As Eat[Bottom] = As.contra(cAsA)
val contra1_2: EatF[Top, Unit] As EatF[Bottom, Unit] = As.contra1_2(cAsA)
val contra2_2: Eatꟻ[Unit, Top] As Eatꟻ[Unit, Bottom] = As.contra2_2(cAsA)
diff --git a/tests/shared/src/test/scala/cats/tests/BifoldableSuite.scala b/tests/shared/src/test/scala/cats/tests/BifoldableSuite.scala
new file mode 100644
index 0000000000..f5821e1cde
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/BifoldableSuite.scala
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Bifoldable
+import cats.laws.discipline.{BifoldableTests, SerializableTests}
+import cats.syntax.either._
+import cats.syntax.eq._
+
+class BifoldableSuite extends CatsSuite {
+ type EitherEither[A, B] = Either[Either[A, B], Either[A, B]]
+ val eitherComposeEither: Bifoldable[EitherEither] =
+ Bifoldable[Either].compose[Either]
+
+ checkAll("Either compose Either", BifoldableTests(eitherComposeEither).bifoldable[Int, Int, Int])
+ checkAll("Bifoldable[Either compose Either]", SerializableTests.serializable(eitherComposeEither))
+
+ test("bifold works for 2 monoids") {
+ assert(Bifoldable[Either].bifold(Either.right[Int, String]("something")) === ((0, "something")))
+ assert(Bifoldable[Either].bifold(Either.left[Int, String](5)) === ((5, "")))
+ }
+}
diff --git a/tests/shared/src/test/scala/cats/tests/BifunctorSuite.scala b/tests/shared/src/test/scala/cats/tests/BifunctorSuite.scala
new file mode 100644
index 0000000000..96b0a25ac6
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/BifunctorSuite.scala
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Bifunctor, Functor}
+import cats.laws.discipline.{BifunctorTests, FunctorTests, SerializableTests}
+
+class BifunctorSuite extends CatsSuite {
+ type Tuple2Either[A, B] = (Either[A, B], Either[A, B])
+ val tuple2ComposeEither: Bifunctor[Tuple2Either] =
+ Bifunctor[Tuple2].compose[Either]
+
+ checkAll("Tuple2 compose Either",
+ BifunctorTests(tuple2ComposeEither).bifunctor[Int, Int, Int, String, String, String]
+ )
+ checkAll("Bifunctor[Tuple2 compose Either]", SerializableTests.serializable(tuple2ComposeEither))
+
+ {
+ type LeftFunctor[A] = (Either[A, Int], Either[A, Int])
+ implicit val leftFunctor: Functor[LeftFunctor] = tuple2ComposeEither.leftFunctor
+ checkAll("Bifunctor[Tuple2 compose Either].leftFunctor", FunctorTests[LeftFunctor].functor[Int, Int, Int])
+ }
+
+ {
+ type RightFunctor[A] = (Either[Int, A], Either[Int, A])
+ implicit val leftFunctor: Functor[RightFunctor] = tuple2ComposeEither.rightFunctor
+ checkAll("Bifunctor[Tuple2 compose Either].rightFunctor", FunctorTests[RightFunctor].functor[Int, Int, Int])
+ }
+
+ {
+ type Tuple2InsideOption[A, B] = Option[(A, B)]
+ implicit val composedBifunctor: Bifunctor[Tuple2InsideOption] = Functor[Option].composeBifunctor[(*, *)]
+ checkAll(
+ "Bifunctor[Option[(A, B)]",
+ BifunctorTests[Tuple2InsideOption].bifunctor[String, String, String, Int, Int, Int]
+ )
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/BinCodecInvariantMonoidalSuite.scala b/tests/shared/src/test/scala/cats/tests/BinCodecInvariantMonoidalSuite.scala
similarity index 85%
rename from tests/src/test/scala/cats/tests/BinCodecInvariantMonoidalSuite.scala
rename to tests/shared/src/test/scala/cats/tests/BinCodecInvariantMonoidalSuite.scala
index f5bc3ed039..2e885cef65 100644
--- a/tests/src/test/scala/cats/tests/BinCodecInvariantMonoidalSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/BinCodecInvariantMonoidalSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{InvariantMonoidal, InvariantSemigroupal}
diff --git a/tests/src/test/scala/cats/tests/BinestedSuite.scala b/tests/shared/src/test/scala/cats/tests/BinestedSuite.scala
similarity index 74%
rename from tests/src/test/scala/cats/tests/BinestedSuite.scala
rename to tests/shared/src/test/scala/cats/tests/BinestedSuite.scala
index ed7223ebde..f6d2825ef4 100644
--- a/tests/src/test/scala/cats/tests/BinestedSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/BinestedSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Bifoldable, Bifunctor, Bitraverse, Foldable, Functor, Traverse}
diff --git a/tests/shared/src/test/scala/cats/tests/BitSetSuite.scala b/tests/shared/src/test/scala/cats/tests/BitSetSuite.scala
new file mode 100644
index 0000000000..f3989a0566
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/BitSetSuite.scala
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.syntax.show._
+import org.scalacheck.Arbitrary
+import org.scalacheck.Arbitrary.arbitrary
+import scala.collection.immutable.BitSet
+import cats.syntax.eq._
+import org.scalacheck.Prop._
+
+class BitSetSuite extends CatsSuite {
+ implicit val arbitraryBitSet: Arbitrary[BitSet] =
+ Arbitrary(arbitrary[List[Short]].map(ns => BitSet(ns.map(_ & 0xffff): _*)))
+
+ test("show BitSet") {
+ assert(BitSet(1, 1, 2, 3).show === "BitSet(1, 2, 3)")
+ assert(BitSet.empty.show === "BitSet()")
+
+ forAll { (fs: BitSet) =>
+ assert(fs.show === (fs.toString))
+ }
+ }
+
+}
diff --git a/tests/shared/src/test/scala/cats/tests/BitraverseSuite.scala b/tests/shared/src/test/scala/cats/tests/BitraverseSuite.scala
new file mode 100644
index 0000000000..ccfe0d25f1
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/BitraverseSuite.scala
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Bitraverse
+import cats.laws.discipline.{BitraverseTests, SerializableTests}
+
+class BitraverseSuite extends CatsSuite {
+ type EitherTuple2[A, B] = Either[(A, B), (A, B)]
+ val eitherComposeTuple2: Bitraverse[EitherTuple2] =
+ Bitraverse[Either].compose[Tuple2]
+
+ checkAll("Either compose Tuple2",
+ BitraverseTests(eitherComposeTuple2).bitraverse[Option, Int, Int, Int, String, String, String]
+ )
+ checkAll("Bitraverse[Either compose Tuple2]", SerializableTests.serializable(eitherComposeTuple2))
+}
diff --git a/tests/shared/src/test/scala/cats/tests/BoundedEnumerableSuite.scala b/tests/shared/src/test/scala/cats/tests/BoundedEnumerableSuite.scala
new file mode 100644
index 0000000000..ab3ecf0b92
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/BoundedEnumerableSuite.scala
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.kernel.BoundedEnumerable
+import cats.syntax.eq._
+
+class BoundedEnumerableSuite extends CatsSuite {
+
+ test("membersAscending") {
+ assert(BoundedEnumerable[Boolean].membersAscending.toList === (List(false, true)))
+ }
+
+ test("membersDescending") {
+ assert(BoundedEnumerable[Boolean].membersDescending.toList === (List(true, false)))
+ }
+
+ test("cycleNext") {
+ assert(BoundedEnumerable[Boolean].cycleNext(false) === true)
+ }
+
+ test("cyclePrevious") {
+ assert(BoundedEnumerable[Boolean].cyclePrevious(false) === true)
+ }
+
+}
diff --git a/tests/shared/src/test/scala/cats/tests/CategorySuite.scala b/tests/shared/src/test/scala/cats/tests/CategorySuite.scala
new file mode 100644
index 0000000000..75063e8a2f
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/CategorySuite.scala
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Endo
+import cats.arrow.Category
+import cats.kernel.laws.discipline.MonoidTests
+import cats.laws.discipline.{MiniInt, MonoidKTests, SerializableTests}
+import cats.laws.discipline.eq.catsLawsEqForFn1Exhaustive
+import cats.laws.discipline.arbitrary.{catsLawsArbitraryForMiniInt, catsLawsCogenForMiniInt}
+
+class CategorySuite extends CatsSuite {
+ val functionCategory = Category[Function1]
+
+ checkAll("Category[Function1].algebraK", MonoidKTests[Endo](functionCategory.algebraK).monoidK[MiniInt])
+ checkAll("Category[Function1].algebraK", SerializableTests.serializable(functionCategory.algebraK))
+
+ val functionAlgebra = functionCategory.algebra[MiniInt]
+ checkAll("Category[Function1].algebra[MiniInt]", MonoidTests[Endo[MiniInt]](functionAlgebra).monoid)
+}
diff --git a/tests/src/test/scala/cats/tests/CatsSuite.scala b/tests/shared/src/test/scala/cats/tests/CatsSuite.scala
similarity index 50%
rename from tests/src/test/scala/cats/tests/CatsSuite.scala
rename to tests/shared/src/test/scala/cats/tests/CatsSuite.scala
index 6e3f4cb7d7..b90ecb6593 100644
--- a/tests/src/test/scala/cats/tests/CatsSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/CatsSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.platform.Platform
diff --git a/tests/src/test/scala/cats/tests/ChainSuite.scala b/tests/shared/src/test/scala/cats/tests/ChainSuite.scala
similarity index 62%
rename from tests/src/test/scala/cats/tests/ChainSuite.scala
rename to tests/shared/src/test/scala/cats/tests/ChainSuite.scala
index 23e4505a20..b25e2022e3 100644
--- a/tests/src/test/scala/cats/tests/ChainSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/ChainSuite.scala
@@ -1,32 +1,51 @@
-package cats.tests
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats
+package tests
-import cats.{Align, Alternative, CoflatMap, Monad, Show, Traverse, TraverseFilter}
import cats.data.Chain
-import cats.data.Chain.==:
import cats.data.Chain.`:==`
-import cats.kernel.{Eq, Hash, Monoid, Order, PartialOrder, Semigroup}
-import cats.kernel.laws.discipline.{EqTests, HashTests, MonoidTests, OrderTests, PartialOrderTests}
-import cats.laws.discipline.{
- AlignTests,
- AlternativeTests,
- CoflatMapTests,
- MonadTests,
- SerializableTests,
- ShortCircuitingTests,
- TraverseFilterTests,
- TraverseTests
-}
+import cats.data.Chain.==:
+import cats.kernel.laws.discipline.EqTests
+import cats.kernel.laws.discipline.HashTests
+import cats.kernel.laws.discipline.MonoidTests
+import cats.kernel.laws.discipline.OrderTests
+import cats.kernel.laws.discipline.PartialOrderTests
+import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
+import cats.syntax.eq._
import cats.syntax.foldable._
import cats.syntax.semigroup._
-import cats.syntax.eq._
+import org.scalacheck.Arbitrary
+import org.scalacheck.Gen
import org.scalacheck.Prop._
class ChainSuite extends CatsSuite {
checkAll("Chain[Int]", AlternativeTests[Chain].alternative[Int, Int, Int])
checkAll("Alternative[Chain]", SerializableTests.serializable(Alternative[Chain]))
+ // Traverse behaviour discriminates on the Runtime type of the Applicative
checkAll("Chain[Int] with Option", TraverseTests[Chain].traverse[Int, Int, Int, Set[Int], Option, Option])
+ checkAll("Chain[Int] with Eval", TraverseTests[Chain].traverse[Int, Int, Int, Set[Int], Eval, Eval])
checkAll("Traverse[Chain]", SerializableTests.serializable(Traverse[Chain]))
checkAll("Chain[Int]", MonadTests[Chain].monad[Int, Int, Int])
@@ -99,16 +118,18 @@ class ChainSuite extends CatsSuite {
test("seq-like pattern match") {
Chain(1, 2, 3) match {
case Chain(a, b, c) => assert((a, b, c) === ((1, 2, 3)))
+ case other => fail(other.show)
}
Chain(1, 2, 3) match {
case h ==: t => assert((h, t) === 1 -> Chain(2, 3))
+ case other => fail(other.show)
}
Chain(1, 2, 3) match {
case init :== last => assert((init, last) === Chain(1, 2) -> 3)
+ case other => fail(other.show)
}
-
}
test("size is consistent with toList.size") {
@@ -117,6 +138,56 @@ class ChainSuite extends CatsSuite {
}
}
+ test("knownSize should be consistent with size") {
+ forAll { (cu: Chain[Unit]) =>
+ val expected = cu.size match {
+ case size @ (0L | 1L) => size
+ case _ => -1L
+ }
+
+ assertEquals(cu.knownSize, expected)
+ }
+ }
+
+ test("lengthCompare and sizeCompare should be consistent with length and size") {
+ forAll { (cu: Chain[Unit], diff: Byte) =>
+ val testLen = cu.length + diff
+ val testSize = cu.size + diff
+
+ val expectedSignumLen = math.signum(cu.length.compareTo(testLen))
+ val expectedSignumSize = math.signum(cu.size.compareTo(testSize))
+
+ val obtainedSignumLen = math.signum(cu.lengthCompare(testLen))
+ val obtainedSignumSize = math.signum(cu.sizeCompare(testSize))
+
+ assertEquals(obtainedSignumLen, expectedSignumLen)
+ assertEquals(obtainedSignumSize, expectedSignumSize)
+ }
+ }
+ test("lengthCompare and sizeCompare should be consistent with length and size (Chain.Wrap stressed)") {
+ //
+ // Similar to the previous test but stresses handling Chain.Wrap cases.
+ //
+
+ // Range as `Seq` can has huge size without keeping any elements in it.
+ val seqGen: Gen[Seq[Int]] = Gen.chooseNum(2, Int.MaxValue).map(0 until _)
+ val testValGen: Gen[Long] = Arbitrary.arbitrary[Long]
+
+ // Disable shrinking since it can lead to re-building of range into a regular `Seq`.
+ forAllNoShrink(seqGen, testValGen) { (seq, testVal) =>
+ val ci = Chain.fromSeq(seq) // should produce `Chain.Wrap`
+
+ val expectedSignumLen = math.signum(seq.length.toLong.compareTo(testVal))
+ val expectedSignumSize = math.signum(seq.size.toLong.compareTo(testVal))
+
+ val obtainedSignumLen = math.signum(ci.lengthCompare(testVal))
+ val obtainedSignumSize = math.signum(ci.sizeCompare(testVal))
+
+ assertEquals(obtainedSignumLen, expectedSignumLen)
+ assertEquals(obtainedSignumSize, expectedSignumSize)
+ }
+ }
+
test("filterNot and then exists should always be false") {
forAll { (ci: Chain[Int], f: Int => Boolean) =>
assert(ci.filterNot(f).exists(f) === false)
@@ -153,6 +224,28 @@ class ChainSuite extends CatsSuite {
}
}
+ test("fromOption should be consistent with one") {
+ val expected = Chain.one(())
+ val obtained = Chain.fromOption(Some(()))
+
+ assert(obtained.getClass eq expected.getClass)
+ assert(obtained === expected)
+ }
+
+ test("fromSeq should be consistent with one") {
+ val expected = Chain.one(())
+ val obtained = Chain.fromSeq(() :: Nil)
+ assert(obtained.getClass eq expected.getClass)
+ assert(obtained === expected)
+ }
+
+ test("fromIterableOnce should be consistent with one") {
+ val expected = Chain.one(())
+ val obtained = Chain.fromIterableOnce(Iterator.single(()))
+ assert(obtained.getClass eq expected.getClass)
+ assert(obtained === expected)
+ }
+
test("fromSeq . toVector is id") {
forAll { (ci: Chain[Int]) =>
assert(Chain.fromSeq(ci.toVector) === ci)
@@ -247,6 +340,8 @@ class ChainSuite extends CatsSuite {
test("a.isEmpty == (a eq Chain.nil)") {
assert(Chain.fromSeq(Nil) eq Chain.nil)
+ assert(Chain.fromOption(None) eq Chain.nil)
+ assert(Chain.fromIterableOnce(Iterator.empty) eq Chain.nil)
forAll { (a: Chain[Int]) =>
assert(a.isEmpty == (a eq Chain.nil))
@@ -287,6 +382,12 @@ class ChainSuite extends CatsSuite {
}
}
+ test("Chain#distinctBy is consistent with List#distinctBy") {
+ forAll { (a: Chain[Int], f: Int => String) =>
+ assertEquals(a.distinctBy(f).toList, a.toList.distinctBy(f))
+ }
+ }
+
test("=== is consistent with == (issue #2540)") {
assertEquals(Chain.one(1) |+| Chain.one(2) |+| Chain.one(3), Chain.fromSeq(List(1, 2, 3)))
@@ -341,4 +442,44 @@ class ChainSuite extends CatsSuite {
assert(sumAll == chain.iterator.sum)
}
+
+ test("foldRight(b)(fn) == toList.foldRight(b)(fn)") {
+ forAll { (chain: Chain[Int], init: Long, fn: (Int, Long) => Long) =>
+ assert(chain.foldRight(init)(fn) == chain.toList.foldRight(init)(fn))
+ }
+ }
+
+ private val genChainDropTakeArgs =
+ Arbitrary.arbitrary[Chain[Int]].flatMap { chain =>
+ // Bias to values close to the length
+ Gen
+ .oneOf(
+ Gen.choose(Int.MinValue, Int.MaxValue),
+ Gen.choose(-1, chain.length.toInt + 1)
+ )
+ .map((chain, _))
+ }
+
+ test("drop(cnt).toList == toList.drop(cnt)") {
+ forAll(genChainDropTakeArgs) { case (chain: Chain[Int], count: Int) =>
+ assertEquals(chain.drop(count).toList, chain.toList.drop(count))
+ }
+ }
+
+ test("dropRight(cnt).toList == toList.dropRight(cnt)") {
+ forAll(genChainDropTakeArgs) { case (chain: Chain[Int], count: Int) =>
+ assertEquals(chain.dropRight(count).toList, chain.toList.dropRight(count))
+ }
+ }
+ test("take(cnt).toList == toList.take(cnt)") {
+ forAll(genChainDropTakeArgs) { case (chain: Chain[Int], count: Int) =>
+ assertEquals(chain.take(count).toList, chain.toList.take(count))
+ }
+ }
+
+ test("takeRight(cnt).toList == toList.takeRight(cnt)") {
+ forAll(genChainDropTakeArgs) { case (chain: Chain[Int], count: Int) =>
+ assertEquals(chain.takeRight(count).toList, chain.toList.takeRight(count))
+ }
+ }
}
diff --git a/tests/src/test/scala/cats/tests/CokleisliSuite.scala b/tests/shared/src/test/scala/cats/tests/CokleisliSuite.scala
similarity index 67%
rename from tests/src/test/scala/cats/tests/CokleisliSuite.scala
rename to tests/shared/src/test/scala/cats/tests/CokleisliSuite.scala
index bd1ab83d15..5d29a740f9 100644
--- a/tests/src/test/scala/cats/tests/CokleisliSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/CokleisliSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Contravariant, Id, Monad, MonoidK, SemigroupK, Semigroupal}
@@ -61,18 +82,13 @@ class CokleisliSuite extends SlowCatsSuite {
)
checkAll("Arrow[Cokleisli[NonEmptyList, *, *]]", SerializableTests.serializable(Arrow[Cokleisli[NonEmptyList, *, *]]))
- {
- implicit def cokleisliIdEq[A, B](implicit evidence: Eq[A => B]): Eq[Cokleisli[Id, A, B]] =
- Eq.by[Cokleisli[Id, A, B], A => B](_.run)
-
- checkAll(
- "Cokleisli[Id, MiniInt, MiniInt]",
- CommutativeArrowTests[Cokleisli[Id, *, *]].commutativeArrow[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, MiniInt]
- )
- checkAll("CommutativeArrow[Cokleisli[Id, *, *]]",
- SerializableTests.serializable(CommutativeArrow[Cokleisli[Id, *, *]])
- )
- }
+ checkAll(
+ "Cokleisli[Id, MiniInt, MiniInt]",
+ CommutativeArrowTests[Cokleisli[Id, *, *]].commutativeArrow[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, MiniInt]
+ )
+ checkAll("CommutativeArrow[Cokleisli[Id, *, *]]",
+ SerializableTests.serializable(CommutativeArrow[Cokleisli[Id, *, *]])
+ )
test("contramapValue with Id consistent with lmap") {
forAll { (c: Cokleisli[Id, Int, Long], f: MiniInt => Int) =>
diff --git a/tests/shared/src/test/scala/cats/tests/ComposeSuite.scala b/tests/shared/src/test/scala/cats/tests/ComposeSuite.scala
new file mode 100644
index 0000000000..4b19f9516f
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/ComposeSuite.scala
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Endo
+import cats.arrow.Compose
+import cats.kernel.laws.discipline.SemigroupTests
+import cats.laws.discipline.{MiniInt, SemigroupKTests, SerializableTests}
+import cats.laws.discipline.eq.catsLawsEqForFn1Exhaustive
+import cats.laws.discipline.arbitrary._
+import cats.syntax.compose._
+
+class ComposeSuite extends CatsSuite {
+ val functionCompose = Compose[Function1]
+
+ checkAll("Compose[Function1].algebraK", SemigroupKTests[Endo](functionCompose.algebraK).semigroupK[MiniInt])
+ checkAll("Compose[Function1].algebraK", SerializableTests.serializable(functionCompose.algebraK))
+
+ val functionAlgebra = functionCompose.algebra[MiniInt]
+ checkAll("Compose[Function1].algebra[MiniInt]", SemigroupTests[Endo[MiniInt]](functionAlgebra).semigroup)
+
+ test("syntax") {
+ assertEquals((((_: Int) + 1) <<< ((_: Int) / 2))(2), 2)
+ assertEquals((((_: Int) + 1) >>> ((_: Int) / 2))(5), 3)
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/ConstSuite.scala b/tests/shared/src/test/scala/cats/tests/ConstSuite.scala
similarity index 66%
rename from tests/src/test/scala/cats/tests/ConstSuite.scala
rename to tests/shared/src/test/scala/cats/tests/ConstSuite.scala
index 2e45d1095f..62550af631 100644
--- a/tests/src/test/scala/cats/tests/ConstSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/ConstSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
@@ -5,6 +26,7 @@ import cats.data.{Const, NonEmptyList}
import cats.kernel.Semigroup
import cats.kernel.laws.discipline.{
EqTests,
+ HashTests,
LowerBoundedTests,
MonoidTests,
OrderTests,
@@ -12,12 +34,12 @@ import cats.kernel.laws.discipline.{
SemigroupTests,
UpperBoundedTests
}
-import cats.laws.discipline._
import cats.laws.discipline.SemigroupalTests.Isomorphisms
+import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
-import cats.syntax.show._
-import cats.tests.Helpers.{CMono, CSemi}
import cats.syntax.eq._
+import cats.syntax.show._
+import cats.tests.Helpers.{CMono, CSemi, Semi}
import org.scalacheck.Prop._
class ConstSuite extends CatsSuite {
@@ -79,9 +101,16 @@ class ConstSuite extends CatsSuite {
checkAll("Const[String, Int]", ContravariantTests[Const[String, *]].contravariant[Int, Int, Int])
checkAll("Contravariant[Const[String, *]]", SerializableTests.serializable(Contravariant[Const[String, *]]))
- checkAll("Const[String, Int]", ContravariantMonoidalTests[Const[String, *]].contravariantMonoidal[Int, Int, Int])
- checkAll("ContravariantMonoidal[Const[String, *]]",
- SerializableTests.serializable(ContravariantMonoidal[Const[String, *]])
+ checkAll("ContravariantMonoidal[Const[Int, *]]",
+ ContravariantMonoidalTests[Const[Int, *]].contravariantMonoidal[Int, Int, Int]
+ )
+ checkAll("ContravariantMonoidal[Const[Int, *]]", SerializableTests.serializable(ContravariantMonoidal[Const[Int, *]]))
+
+ checkAll("ContravariantSemigroupal[Const[Semi, *]]",
+ ContravariantSemigroupalTests[Const[Semi, *]].contravariantSemigroupal[Int, Int, Int]
+ )
+ checkAll("ContravariantSemigroupal[Const[Semi, *]]",
+ SerializableTests.serializable(ContravariantSemigroupal[Const[Semi, *]])
)
checkAll("Const[*, *]", BifoldableTests[Const].bifoldable[Int, Int, Int])
@@ -99,8 +128,8 @@ class ConstSuite extends CatsSuite {
forAll { (const: Const[Int, String]) =>
assert(const.show.startsWith("Const(") === true)
const.show.contains(const.getConst.show)
- assert(const.show === (implicitly[Show[Const[Int, String]]].show(const)))
- assert(const.show === (const.retag[Boolean].show))
+ assert(const.show === Show[Const[Int, String]].show(const))
+ assert(const.show === const.retag[Boolean].show)
}
}
@@ -109,7 +138,7 @@ class ConstSuite extends CatsSuite {
{
implicit val iso: Isomorphisms[Const[CMono, *]] =
- Isomorphisms.invariant[Const[CMono, *]](Const.catsDataFunctorForConst)
+ Isomorphisms.invariant[Const[CMono, *]](Const.catsDataTraverseForConst)
checkAll("Const[CMono, Int]", CommutativeApplicativeTests[Const[CMono, *]].commutativeApplicative[Int, Int, Int])
checkAll("CommutativeApplicative[Const[CMono, *]]",
SerializableTests.serializable(CommutativeApplicative[Const[CMono, *]])
@@ -118,4 +147,23 @@ class ConstSuite extends CatsSuite {
checkAll("Const[CSemi, Int]", CommutativeApplyTests[Const[CSemi, *]].commutativeApply[Int, Int, Int])
checkAll("CommutativeApply[Const[CSemi, *]]", SerializableTests.serializable(CommutativeApply[Const[CSemi, *]]))
+
+ checkAll("Hash[Const[Int, String]]", HashTests[Const[Int, String]].hash)
+ checkAll("Hash[Const[Int, String]]", SerializableTests.serializable(Hash[Const[Int, String]]))
+
+ checkAll("MonoidK[Const[Int, *]]", MonoidKTests[Const[Int, *]].monoidK[Int])
+ checkAll("MonoidK[Const[Int, *]]", SerializableTests.serializable(MonoidK[Const[Int, *]]))
+
+ checkAll("SemigroupK[Const[Int, *]]", SemigroupKTests[Const[Semi, *]].semigroupK[Int])
+ checkAll("SemigroupK[Const[Int, *]]", SerializableTests.serializable(SemigroupK[Const[Semi, *]]))
+}
+
+object ConstSuite {
+ def summonInstances[A, B: Hash](): Unit = {
+ InvariantMonoidal[Const[Int, *]]
+ Invariant[Const[A, *]]
+ Functor[Const[A, *]]
+ Eq[Const[B, Int]]
+ ()
+ }
}
diff --git a/tests/src/test/scala/cats/tests/ContTSuite.scala b/tests/shared/src/test/scala/cats/tests/ContTSuite.scala
similarity index 81%
rename from tests/src/test/scala/cats/tests/ContTSuite.scala
rename to tests/shared/src/test/scala/cats/tests/ContTSuite.scala
index fc104d24ca..3299470607 100644
--- a/tests/src/test/scala/cats/tests/ContTSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/ContTSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import java.util.concurrent.atomic.AtomicInteger
@@ -19,12 +40,7 @@ class ContTSuite extends CatsSuite {
implicit def eqContT[M[_], A, B](implicit arbFn: Arbitrary[B => M[A]], eqMA: Eq[M[A]]): Eq[ContT[M, A, B]] = {
val genItems = Gen.listOfN(100, arbFn.arbitrary)
val fns = genItems.sample.get
- new Eq[ContT[M, A, B]] {
- def eqv(a: ContT[M, A, B], b: ContT[M, A, B]) =
- fns.forall { fn =>
- eqMA.eqv(a.run(fn), b.run(fn))
- }
- }
+ (a, b) => fns.forall(fn => eqMA.eqv(a.run(fn), b.run(fn)))
}
checkAll("ContT[Function0, Int, *]", MonadTests[ContT[Function0, Int, *]].monad[Int, String, Int])
@@ -179,6 +195,16 @@ class ContTSuite extends CatsSuite {
assert(contT.run(Eval.now(_)).value === maxIters)
}
+ // test from issue 2950
+ test("ContT.map stack-safety") {
+ val maxIters = 20000
+ var k = ContT.defer[Eval, Int, Int](0)
+ for (_ <- 1 to maxIters) {
+ k = k.map(x => x + 1)
+ }
+ assert(k.run(_.pure[Eval]).value == maxIters)
+ }
+
test("ContT.callCC short-circuits and invokes the continuation") {
forAll { (cb: Unit => Eval[Int]) =>
var shouldNotChange = false
diff --git a/tests/src/test/scala/cats/tests/ContravariantSuite.scala b/tests/shared/src/test/scala/cats/tests/ContravariantSuite.scala
similarity index 67%
rename from tests/src/test/scala/cats/tests/ContravariantSuite.scala
rename to tests/shared/src/test/scala/cats/tests/ContravariantSuite.scala
index 14107f6373..cb50ae2960 100644
--- a/tests/src/test/scala/cats/tests/ContravariantSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/ContravariantSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Contravariant, ContravariantMonoidal, ContravariantSemigroupal}
diff --git a/tests/shared/src/test/scala/cats/tests/DurationSuite.scala b/tests/shared/src/test/scala/cats/tests/DurationSuite.scala
new file mode 100644
index 0000000000..1f50bb20d5
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/DurationSuite.scala
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Show
+import cats.laws.discipline.SerializableTests
+import scala.concurrent.duration.{Duration, DurationInt}
+import cats.syntax.eq._
+
+class DurationSuite extends CatsSuite {
+ checkAll("Show[Duration]", SerializableTests.serializable(Show[Duration]))
+
+ test("show works for FiniteDuration") {
+ assert(Show[Duration].show(23.minutes) === "23 minutes")
+ }
+
+ test("show works for non-finite durations") {
+ assert(Show[Duration].show(Duration.Inf) === "Duration.Inf")
+ assert(Show[Duration].show(Duration.MinusInf) === "Duration.MinusInf")
+ assert(Show[Duration].show(Duration.Undefined) === "Duration.Undefined")
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/EitherKSuite.scala b/tests/shared/src/test/scala/cats/tests/EitherKSuite.scala
similarity index 69%
rename from tests/src/test/scala/cats/tests/EitherKSuite.scala
rename to tests/shared/src/test/scala/cats/tests/EitherKSuite.scala
index 855da4daf2..766a5950c7 100644
--- a/tests/src/test/scala/cats/tests/EitherKSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/EitherKSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
diff --git a/tests/src/test/scala/cats/tests/EitherSuite.scala b/tests/shared/src/test/scala/cats/tests/EitherSuite.scala
similarity index 82%
rename from tests/src/test/scala/cats/tests/EitherSuite.scala
rename to tests/shared/src/test/scala/cats/tests/EitherSuite.scala
index 82e783e883..3d0e6cac73 100644
--- a/tests/src/test/scala/cats/tests/EitherSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/EitherSuite.scala
@@ -1,12 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
-import cats.data.{EitherT, NonEmptyChain, NonEmptyList, NonEmptySet, Validated}
+import cats.data.{EitherT, NonEmptyChain, NonEmptyList, NonEmptySet, NonEmptyVector, Validated}
+import cats.syntax.bifunctor._
import cats.kernel.laws.discipline.{EqTests, MonoidTests, OrderTests, PartialOrderTests, SemigroupTests}
import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
import cats.laws.discipline.SemigroupalTests.Isomorphisms
import cats.syntax.either._
+
import scala.util.Try
import cats.syntax.eq._
import org.scalacheck.Prop._
@@ -85,9 +108,9 @@ class EitherSuite extends CatsSuite {
test("implicit instances resolve specifically") {
val eq = cats.kernel.instances.either.catsStdEqForEither[Int, String]
- assert(!eq.isInstanceOf[PartialOrder[_]])
- assert(!eq.isInstanceOf[Order[_]])
- assert(!partialOrder.isInstanceOf[Order[_]])
+ assert(!eq.isInstanceOf[PartialOrder[?]])
+ assert(!eq.isInstanceOf[Order[?]])
+ assert(!partialOrder.isInstanceOf[Order[?]])
}
test("show isn't empty") {
@@ -159,6 +182,7 @@ class EitherSuite extends CatsSuite {
assert(Either.leftNes[String, Int](s) === (Either.left[NonEmptySet[String], Int](NonEmptySet.one(s))))
}
}
+
test("rightNes is consistent with right") {
forAll { (i: Int) =>
assert(Either.rightNes[String, Int](i) === (Either.right[NonEmptySet[String], Int](i)))
@@ -276,6 +300,7 @@ class EitherSuite extends CatsSuite {
assert(x.isLeft === (x.toValidated.isInvalid))
assert(x.isLeft === (x.toValidatedNel.isInvalid))
assert(x.isLeft === (x.toValidatedNec.isInvalid))
+ assert(x.isLeft === (x.leftLiftTo[NonEmptyVector].isLeft))
assert(Option(x.isLeft) === (x.toEitherT[Option].isLeft))
}
}
@@ -348,6 +373,22 @@ class EitherSuite extends CatsSuite {
assert(either.toEitherNel === (Either.right[NonEmptyList[String], Int](42)))
}
+ test("leftLiftTo Left") {
+ forAll { (y: String) =>
+ assert(
+ y.asLeft[Int].leftLiftTo[NonEmptyVector] === Either.left[NonEmptyVector[String], Int](
+ NonEmptyVector.one(y)
+ )
+ )
+ }
+ }
+
+ test("leftLiftTo Right") {
+ forAll { (x: Int) =>
+ assert(x.asRight[String].leftLiftTo[NonEmptyVector] === (Either.right[NonEmptyVector[String], Int](x)))
+ }
+ }
+
test("ap consistent with Applicative") {
val fab = implicitly[Applicative[Either[String, *]]]
forAll { (fa: Either[String, Int], f: Int => String) =>
@@ -373,6 +414,35 @@ class EitherSuite extends CatsSuite {
assert(either.leftFlatMap(f) === (either.swap.flatMap(a => f(a).swap).swap))
}
}
+
+ test("leftFlatMapOrKeep consistent with leftMapOrKeep") {
+ forAll { (either: Either[String, Int], pf: PartialFunction[String, String]) =>
+ val liftedPF: PartialFunction[String, Either[String, Int]] = { case a =>
+ Either.left[String, Int](pf.applyOrElse(a, identity[String]))
+ }
+ assert(either.leftFlatMapOrKeep(liftedPF) === either.leftMapOrKeep(pf))
+ }
+ }
+
+ test("leftFlatMapOrKeep consistent with swap and then flatMapOrKeep") {
+ import cats.syntax.monad._
+
+ forAll { (either: Either[String, Int], pf: PartialFunction[String, Either[String, Int]]) =>
+ assert(either.leftFlatMapOrKeep(pf) === either.swap.flatMapOrKeep { case a =>
+ pf.applyOrElse(a, (_: String) => either).swap
+ }.swap)
+ }
+ }
+
+ test("raiseWhen raises when true") {
+ val result = Either.raiseWhen(true)("ok")
+ assert(result === Left("ok"))
+ }
+
+ test("raiseUnless raises when false") {
+ val result = Either.raiseUnless(false)("ok")
+ assert(result === Left("ok"))
+ }
}
final class EitherInstancesSuite extends munit.FunSuite {
diff --git a/tests/src/test/scala/cats/tests/EitherTSuite.scala b/tests/shared/src/test/scala/cats/tests/EitherTSuite.scala
similarity index 86%
rename from tests/src/test/scala/cats/tests/EitherTSuite.scala
rename to tests/shared/src/test/scala/cats/tests/EitherTSuite.scala
index 515a1f3eff..564c26721e 100644
--- a/tests/src/test/scala/cats/tests/EitherTSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/EitherTSuite.scala
@@ -1,7 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
-import cats.data.{EitherT, State}
+import cats.data.{EitherT, Ior, IorT, State}
import cats.kernel.laws.discipline.{EqTests, MonoidTests, OrderTests, PartialOrderTests, SemigroupTests}
import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
@@ -17,6 +38,12 @@ class EitherTSuite extends CatsSuite {
implicit val iso: Isomorphisms[EitherT[ListWrapper, String, *]] = Isomorphisms
.invariant[EitherT[ListWrapper, String, *]](EitherT.catsDataFunctorForEitherT(ListWrapper.functor))
+ // Test instance summoning
+ def summon[F[_]: Traverse](): Unit = {
+ Bifunctor[EitherT[F, *, *]]
+ Bifoldable[EitherT[F, *, *]]
+ }
+
checkAll("EitherT[Eval, String, *]", DeferTests[EitherT[Eval, String, *]].defer[Int])
{
@@ -53,6 +80,20 @@ class EitherTSuite extends CatsSuite {
)
}
+ {
+ // if a Foldable for F is defined
+ implicit val F: Foldable[ListWrapper] = ListWrapper.foldable
+
+ checkAll("EitherT[ListWrapper, Int, *]", FoldableTests[EitherT[ListWrapper, Int, *]].foldable[Int, Int])
+ checkAll("Foldable[EitherT[ListWrapper, Int, *]]",
+ SerializableTests.serializable(Foldable[EitherT[ListWrapper, Int, *]])
+ )
+ checkAll("EitherT[ListWrapper, *, *]", BifoldableTests[EitherT[ListWrapper, *, *]].bifoldable[Int, Int, Int])
+ checkAll("Bifoldable[EitherT[ListWrapper, *, *]]",
+ SerializableTests.serializable(Bifoldable[EitherT[ListWrapper, *, *]])
+ )
+ }
+
{
// if a Traverse for F is defined
implicit val F: Traverse[ListWrapper] = ListWrapper.traverse
@@ -69,7 +110,6 @@ class EitherTSuite extends CatsSuite {
checkAll("Bitraverse[EitherT[ListWrapper, *, *]]",
SerializableTests.serializable(Bitraverse[EitherT[ListWrapper, *, *]])
)
-
}
{
@@ -405,6 +445,24 @@ class EitherTSuite extends CatsSuite {
}
}
+ test("getOrRaise consistent with EitherT.getOrElseF(F.raiseError(e))") {
+ forAll { (eithert: EitherT[Either[String, *], String, Int], error: String) =>
+ assertEquals(
+ obtained = eithert.getOrRaise(error),
+ expected = eithert.getOrElseF(Left(error))
+ )
+ }
+ }
+
+ test("getOrRaise consistent with EitherT.leftMap(_ => error).rethrowT") {
+ forAll { (eithert: EitherT[Either[String, *], String, Int], error: String) =>
+ assertEquals(
+ obtained = eithert.getOrRaise(error),
+ expected = eithert.leftMap(_ => error).rethrowT
+ )
+ }
+ }
+
test("orElse with Id consistent with Either orElse") {
forAll { (eithert: EitherT[Id, String, Int], fallback: EitherT[Id, String, Int]) =>
assert(eithert.orElse(fallback).value === (eithert.value.orElse(fallback.value)))
@@ -616,6 +674,33 @@ class EitherTSuite extends CatsSuite {
}
}
+ test("biSemiflatTap does not change the return value") {
+ type TestEffect[A] = State[List[Int], A]
+ forAll {
+ (eithert: EitherT[TestEffect, String, Int],
+ fa: String => TestEffect[Int],
+ fb: Int => TestEffect[Int],
+ initial: List[Int]
+ ) =>
+ assert(eithert.biSemiflatTap(v => fa(v), v => fb(v)).value.runA(initial) === eithert.value.runA(initial))
+ }
+ }
+
+ test("biSemiflatTap consistent with leftSemiflatTap and semiFlatTap") {
+ type TestEffect[A] = State[List[Int], A]
+ forAll {
+ (eithert: EitherT[TestEffect, String, Int],
+ fa: String => TestEffect[Int],
+ fb: Int => TestEffect[Int],
+ initial: List[Int]
+ ) =>
+ assert(
+ eithert.biSemiflatTap(fa, fb).value.runS(initial) ===
+ eithert.leftSemiflatTap(fa).semiflatTap(fb).value.runS(initial)
+ )
+ }
+ }
+
test("biSemiflatMap consistent with leftSemiflatMap and semiFlatmap") {
forAll { (eithert: EitherT[List, String, Int], fa: String => List[Int], fb: Int => List[String]) =>
assert(eithert.biSemiflatMap(fa, fb) === (eithert.leftSemiflatMap(fa).semiflatMap(fb)))
@@ -659,4 +744,9 @@ class EitherTSuite extends CatsSuite {
}
}
+ test("toIor is consistent with IorT(eitherT.value.map(Ior.fromEither))") {
+ forAll { (eitherT: EitherT[List, String, Int]) =>
+ assert(eitherT.toIor === IorT(eitherT.value.map(Ior.fromEither)))
+ }
+ }
}
diff --git a/tests/shared/src/test/scala/cats/tests/EqSuite.scala b/tests/shared/src/test/scala/cats/tests/EqSuite.scala
new file mode 100644
index 0000000000..a08fa60e96
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/EqSuite.scala
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Contravariant, ContravariantMonoidal, ContravariantSemigroupal, Invariant, Semigroupal}
+import cats.kernel.Eq
+import cats.kernel.laws.discipline.SerializableTests
+import cats.laws.discipline.{ContravariantMonoidalTests, DeferTests, MiniInt}
+import cats.laws.discipline.arbitrary._
+import cats.laws.discipline.eq._
+
+class EqSuite extends CatsSuite {
+ Invariant[Eq]
+ Contravariant[Eq]
+ Semigroupal[Eq]
+ ContravariantSemigroupal[Eq]
+
+ checkAll("Eq", ContravariantMonoidalTests[Eq].contravariantMonoidal[MiniInt, Boolean, Boolean])
+ checkAll("ContravariantMonoidal[Eq]", SerializableTests.serializable(ContravariantMonoidal[Eq]))
+ checkAll("Defer[Eq]", DeferTests[Eq].defer[MiniInt])
+}
diff --git a/tests/shared/src/test/scala/cats/tests/EquivSuite.scala b/tests/shared/src/test/scala/cats/tests/EquivSuite.scala
new file mode 100644
index 0000000000..b4de6aaaa8
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/EquivSuite.scala
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Contravariant, ContravariantMonoidal, ContravariantSemigroupal, Invariant, Semigroupal}
+import cats.laws.discipline.arbitrary._
+import cats.laws.discipline._
+import cats.laws.discipline.eq._
+
+class EquivSuite extends CatsSuite {
+
+ Invariant[Equiv]
+ Contravariant[Equiv]
+ Semigroupal[Equiv]
+ ContravariantSemigroupal[Equiv]
+ ContravariantMonoidal[Equiv]
+
+ checkAll("Contravariant[Equiv]", ContravariantTests[Equiv].contravariant[MiniInt, Int, Boolean])
+ checkAll("Semigroupal[Equiv]", SemigroupalTests[Equiv].semigroupal[MiniInt, Boolean, Boolean])
+ checkAll("ContravariantMonoidal[Equiv]",
+ ContravariantMonoidalTests[Equiv].contravariantMonoidal[MiniInt, Boolean, Boolean]
+ )
+ checkAll("ContravariantMonoidal[Equiv]", SerializableTests.serializable(ContravariantMonoidal[Equiv]))
+ checkAll("Defer[Equiv]", DeferTests[Equiv].defer[MiniInt])
+}
diff --git a/tests/src/test/scala/cats/tests/EvalSuite.scala b/tests/shared/src/test/scala/cats/tests/EvalSuite.scala
similarity index 86%
rename from tests/src/test/scala/cats/tests/EvalSuite.scala
rename to tests/shared/src/test/scala/cats/tests/EvalSuite.scala
index b4df9e3746..3819f36e2e 100644
--- a/tests/src/test/scala/cats/tests/EvalSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/EvalSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Bimonad, CommutativeMonad, Eval, Reducible}
@@ -276,4 +297,17 @@ class EvalSuite extends CatsSuite {
assert(n2 == 1)
}
}
+
+ test("test Defer.recursiveFn example") {
+ val sumTo: Int => Eval[Int] =
+ cats.Defer[Eval].recursiveFn[Int, Int] { recur =>
+
+ { i =>
+ if (i > 0) recur(i - 1).map(_ + i)
+ else Eval.now(0)
+ }
+ }
+
+ assert(sumTo(300000).value == (0 to 300000).sum)
+ }
}
diff --git a/tests/shared/src/test/scala/cats/tests/EvidenceSuite.scala b/tests/shared/src/test/scala/cats/tests/EvidenceSuite.scala
new file mode 100644
index 0000000000..3ad9d8506d
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/EvidenceSuite.scala
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.evidence._
+
+class EvidenceSuite extends CatsSuite {
+
+ test("Is / Leibniz") {
+
+ def cast1[A, B](as: List[A])(implicit ev: A Is B): List[B] =
+ ev.substitute(as)
+ cast1[Int, Int](1 :: 2 :: 3 :: Nil)
+
+ def cast2[A, B](as: List[A])(implicit ev: Leibniz[A, B]): List[B] =
+ ev.substitute(as)
+ cast2[Int, Int](1 :: 2 :: 3 :: Nil)
+
+ }
+
+}
diff --git a/tests/shared/src/test/scala/cats/tests/FiniteDurationSuite.scala b/tests/shared/src/test/scala/cats/tests/FiniteDurationSuite.scala
new file mode 100644
index 0000000000..c682f6e5c9
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/FiniteDurationSuite.scala
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Show
+import cats.laws.discipline.SerializableTests
+import scala.concurrent.duration.{DurationInt, FiniteDuration}
+import cats.syntax.eq._
+
+class FiniteDurationSuite extends CatsSuite {
+ checkAll("Show[FiniteDuration]", SerializableTests.serializable(Show[FiniteDuration]))
+
+ test("show works for FiniteDuration") {
+ assert(Show[FiniteDuration].show(23.minutes) === "23 minutes")
+ assert(Show[FiniteDuration].show(10.seconds) === "10 seconds")
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/FoldableSuite.scala b/tests/shared/src/test/scala/cats/tests/FoldableSuite.scala
similarity index 83%
rename from tests/src/test/scala/cats/tests/FoldableSuite.scala
rename to tests/shared/src/test/scala/cats/tests/FoldableSuite.scala
index c4b75c85eb..cceed901bf 100644
--- a/tests/src/test/scala/cats/tests/FoldableSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/FoldableSuite.scala
@@ -1,24 +1,39 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
-import cats.data.{Const, EitherK, IdT, Ior, Nested, NonEmptyList, NonEmptyStream, NonEmptyVector, OneAnd, Validated}
+import cats.data._
import cats.instances.order._
-import cats.kernel.{Eq, Monoid}
import cats.kernel.compat.scalaVersionSpecific._
import cats.laws.discipline.arbitrary._
-import cats.syntax.alternative._
-import cats.syntax.either._
-import cats.syntax.foldable._
-import cats.syntax.functor._
-import cats.syntax.list._
-import cats.syntax.reducible._
-import cats.syntax.semigroupk._
+import cats.syntax.all._
import org.scalacheck.Arbitrary
-import scala.collection.immutable.{SortedMap, SortedSet}
-import scala.util.Try
-import cats.syntax.eq._
import org.scalacheck.Prop._
+import scala.collection.immutable.SortedMap
+import scala.collection.immutable.SortedSet
+import scala.util.Try
+
@suppressUnusedImportWarningForScalaVersionSpecific
abstract class FoldableSuite[F[_]: Foldable](name: String)(implicit
ArbFInt: Arbitrary[F[Int]],
@@ -168,7 +183,9 @@ abstract class FoldableSuite[F[_]: Foldable](name: String)(implicit
// that might still be in use.
//
// https://github.com/typelevel/cats/pull/3278#discussion_r372841693
- assert(fa.collectSomeFold(g) === (fa.toList.filter(f).fold(m.empty)(m.combine)))
+ @annotation.nowarn("cat=deprecation")
+ val obtained = fa.collectSomeFold(g)
+ assert(obtained === (fa.toList.filter(f).fold(m.empty)(m.combine)))
}
}
@@ -399,7 +416,10 @@ abstract class FoldableSuite[F[_]: Foldable](name: String)(implicit
}
-class FoldableSuiteAdditional extends CatsSuite with ScalaVersionSpecificFoldableSuite {
+class FoldableSuiteAdditional
+ extends CatsSuite
+ with ScalaVersionSpecificFoldableSuite
+ with FoldableSuiteAdditionalStreamSpecific {
// exists method written in terms of foldRight
def contains[F[_]: Foldable, A: Eq](as: F[A], goal: A): Eval[Boolean] =
@@ -421,11 +441,11 @@ class FoldableSuiteAdditional extends CatsSuite with ScalaVersionSpecificFoldabl
val names = List("Aaron", "Betty", "Calvin", "Deirdra")
assert(F.foldMap(names)(_.length) === (names.map(_.length).sum))
val sumM = F.foldM(names, "") { (acc, x) =>
- (Some(acc + x): Option[String])
+ Some(acc + x): Option[String]
}
assert(sumM == Some("AaronBettyCalvinDeirdra"))
val sumMapM = F.foldMapM(names) { x =>
- (Some(x): Option[String])
+ Some(x): Option[String]
}
assert(sumMapM == Some("AaronBettyCalvinDeirdra"))
@@ -465,7 +485,7 @@ class FoldableSuiteAdditional extends CatsSuite with ScalaVersionSpecificFoldabl
val lazySum: Eval[Int] = F.foldRightDefer(large, boom[Int])((elem, acc) => acc.map(_ + elem))
}
- def checkMonadicFoldsStackSafety[F[_]](fromRange: Range => F[Int])(implicit F: Foldable[F]): Unit = {
+ def checkMonadicFoldsStackSafety[F[_]: Foldable](fromRange: Range => F[Int]): Unit = {
def nonzero(acc: Long, x: Int): Option[Long] =
if (x == 0) None else Some(acc + x)
@@ -479,15 +499,15 @@ class FoldableSuiteAdditional extends CatsSuite with ScalaVersionSpecificFoldabl
val src = fromRange(1 to n)
val foldMExpected = n.toLong * (n.toLong + 1) / 2
- val foldMResult = F.foldM(src, 0L)(nonzero)
+ val foldMResult = src.foldM(0L)(nonzero)
assert(foldMResult.get == foldMExpected)
val existsMExpected = true
- val existsMResult = F.existsM(src)(gte(n, _))
+ val existsMResult = src.existsM(gte(n, _))
assert(existsMResult.get == existsMExpected)
val forallMExpected = true
- val forallMResult = F.forallM(src)(gte(0, _))
+ val forallMResult = src.forallM(gte(0, _))
assert(forallMResult.get == forallMExpected)
val findMExpected = Some(n)
@@ -497,8 +517,15 @@ class FoldableSuiteAdditional extends CatsSuite with ScalaVersionSpecificFoldabl
val collectFirstSomeMExpected = Some(n)
val collectFirstSomeMResult = src.collectFirstSomeM(gteSome(n, _))
assert(collectFirstSomeMResult.get == collectFirstSomeMExpected)
+ }
+
+ def checkSlidingNStackSafety[F[_]: Foldable](fromRange: Range => F[Int]): Unit = {
+ val n = 1000
+ val src = fromRange(1 to n)
- ()
+ val sliding2Expected = List.tabulate(n)(i => (i, i + 1)).tail
+ val sliding2Result = src.sliding2
+ assertEquals(sliding2Result, sliding2Expected)
}
test(s"Foldable.iterateRight") {
@@ -514,45 +541,63 @@ class FoldableSuiteAdditional extends CatsSuite with ScalaVersionSpecificFoldabl
}
}
- test("Foldable[List].foldM/existsM/forallM/findM/collectFirstSomeM stack safety") {
- checkMonadicFoldsStackSafety[List](_.toList)
- }
+ test("Foldable[List] monadic folds stack safety")(checkMonadicFoldsStackSafety(_.toList))
+ test("Foldable[List].slidingN stack safety")(checkSlidingNStackSafety(_.toList))
- test("Foldable[Stream].foldM stack safety") {
- checkMonadicFoldsStackSafety[Stream](_.toStream)
- }
+ test("Foldable[Vector] monadic folds stack safety")(checkMonadicFoldsStackSafety(_.toVector))
+ test("Foldable[Vector].slidingN stack safety")(checkSlidingNStackSafety(_.toVector))
- test("Foldable[Vector].foldM/existsM/forallM/findM/collectFirstSomeM stack safety") {
- checkMonadicFoldsStackSafety[Vector](_.toVector)
- }
+ test("Foldable[SortedSet] monadic folds stack safety")(checkMonadicFoldsStackSafety(xs => SortedSet(xs: _*)))
+ test("Foldable[SortedSet].slidingN stack safety")(checkSlidingNStackSafety(xs => SortedSet(xs: _*)))
- test("Foldable[SortedSet].foldM/existsM/forallM/findM/collectFirstSomeM stack safety") {
- checkMonadicFoldsStackSafety[SortedSet](s => SortedSet(s: _*))
+ // Can't checkSlidingNStackSafety because of iteration order.
+ test("Foldable[SortedMap[String, *]] monadic stack safety") {
+ checkMonadicFoldsStackSafety(xs => SortedMap(xs.map(x => x.toString -> x): _*))
}
- test("Foldable[SortedMap[String, *]].foldM/existsM/forallM/findM/collectFirstSomeM stack safety") {
- checkMonadicFoldsStackSafety[SortedMap[String, *]](xs =>
- SortedMap.empty[String, Int] ++ xs.map(x => x.toString -> x).toMap
- )
- }
+ test("Foldable[NonEmptyList] monadic folds stack safety")(
+ checkMonadicFoldsStackSafety(xs => NonEmptyList.fromListUnsafe(xs.toList))
+ )
- test("Foldable[NonEmptyList].foldM/existsM/forallM/findM/collectFirstSomeM stack safety") {
- checkMonadicFoldsStackSafety[NonEmptyList](xs => NonEmptyList.fromListUnsafe(xs.toList))
- }
+ test("Foldable[NonEmptyList].slidingN stack safety")(
+ checkSlidingNStackSafety(xs => NonEmptyList.fromListUnsafe(xs.toList))
+ )
- test("Foldable[NonEmptyVector].foldM/existsM/forallM/findM/collectFirstSomeM stack safety") {
- checkMonadicFoldsStackSafety[NonEmptyVector](xs => NonEmptyVector.fromVectorUnsafe(xs.toVector))
- }
+ test("Foldable[NonEmptyVector] monadic folds stack safety")(
+ checkMonadicFoldsStackSafety(xs => NonEmptyVector.fromVectorUnsafe(xs.toVector))
+ )
+
+ test("Foldable[NonEmptyVector].slidingN stack safety")(
+ checkSlidingNStackSafety(xs => NonEmptyVector.fromVectorUnsafe(xs.toVector))
+ )
- test("Foldable[NonEmptyStream].foldM/existsM/forallM/findM/collectFirstSomeM stack safety") {
- checkMonadicFoldsStackSafety[NonEmptyStream](xs => NonEmptyStream(xs.head, xs.tail: _*))
+ test("Foldable[List] doesn't break substitution") {
+ val result = List.range(0, 10).foldM(List.empty[Int])((accum, elt) => Eval.always(elt :: accum))
+
+ assert(result.value == result.value)
}
+}
+
+// `Stream` is deprecated since Scala 2.13 therefore all tests involving this type are
+// gathered here to suppress deprecation warnings at once.
+@annotation.nowarn("cat=deprecation")
+sealed trait FoldableSuiteAdditionalStreamSpecific { self: FoldableSuiteAdditional =>
+ test("Foldable[Stream] monadic folds stack safety")(checkMonadicFoldsStackSafety(_.toStream))
+ test("Foldable[Stream].slidingN stack safety")(checkSlidingNStackSafety(_.toStream))
+
+ test("Foldable[NonEmptyStream] monadic folds stack safety")(
+ checkMonadicFoldsStackSafety(xs => NonEmptyStream(xs.head, xs.tail: _*))
+ )
+
+ test("Foldable[NonEmptyStream].slidingN stack safety")(
+ checkSlidingNStackSafety(xs => NonEmptyStream(xs.head, xs.tail: _*))
+ )
val F = Foldable[Stream]
def bomb[A]: A = sys.error("boom")
val dangerous = 0 #:: 1 #:: 2 #:: bomb[Int] #:: Stream.empty
- def boom[A]: Stream[A] =
- bomb[A] #:: Stream.empty
+ def boom[A]: Stream[A] = bomb[A] #:: Stream.empty
+
test("Foldable[Stream] doesn't blow up") {
// doesn't blow up - this also ensures it works for infinite streams.
@@ -647,12 +692,6 @@ class FoldableSuiteAdditional extends CatsSuite with ScalaVersionSpecificFoldabl
assert((1 #:: boom[Int]).findM[Id](_ > 0) == Some(1))
assert((1 #:: boom[Int]).collectFirstSomeM[Id, Int](Option.apply) == Some(1))
}
-
- test("Foldable[List] doesn't break substitution") {
- val result = List.range(0, 10).foldM(List.empty[Int])((accum, elt) => Eval.always(elt :: accum))
-
- assert(result.value == result.value)
- }
}
class FoldableListSuite extends FoldableSuite[List]("list") {
@@ -667,7 +706,8 @@ class FoldableSortedSetSuite extends FoldableSuite[SortedSet]("sortedSet") {
def iterator[T](set: SortedSet[T]): Iterator[T] = set.iterator
}
-class FoldableStreamSuite extends FoldableSuite[Stream]("lazyList") {
+@annotation.nowarn("cat=deprecation")
+class FoldableStreamSuite extends FoldableSuite[Stream]("stream") {
def iterator[T](list: Stream[T]): Iterator[T] = list.iterator
}
@@ -709,7 +749,7 @@ class FoldableIdTSuite extends FoldableSuite[IdT[Option, *]]("idT") {
}
class FoldableConstSuite extends FoldableSuite[Const[Int, *]]("const") {
- def iterator[T](const: Const[Int, T]) = None.iterator
+ def iterator[T](const: Const[Int, T]): Iterator[T] = None.iterator
}
class FoldableTuple2Suite extends FoldableSuite[(Int, *)]("tuple2") {
diff --git a/tests/src/test/scala/cats/tests/FuncSuite.scala b/tests/shared/src/test/scala/cats/tests/FuncSuite.scala
similarity index 74%
rename from tests/src/test/scala/cats/tests/FuncSuite.scala
rename to tests/shared/src/test/scala/cats/tests/FuncSuite.scala
index 4f58d15454..45c466b44e 100644
--- a/tests/src/test/scala/cats/tests/FuncSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/FuncSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Applicative, Apply, Contravariant, Functor, Semigroupal, Show}
@@ -62,7 +83,7 @@ class FuncSuite extends CatsSuite {
test("product") {
val f = appFunc { (x: Int) =>
- (Some(x + 10): Option[Int])
+ Some(x + 10): Option[Int]
}
val g = appFunc { (x: Int) =>
List(x * 2)
@@ -74,7 +95,7 @@ class FuncSuite extends CatsSuite {
test("traverse") {
val f = Func.appFunc { (x: Int) =>
- (Some(x + 10): Option[Int])
+ Some(x + 10): Option[Int]
}
val xs = f.traverse(List(1, 2, 3))
assert(xs === (Some(List(11, 12, 13))))
diff --git a/tests/shared/src/test/scala/cats/tests/FunctionKLiftCrossBuildSuite.scala b/tests/shared/src/test/scala/cats/tests/FunctionKLiftCrossBuildSuite.scala
new file mode 100644
index 0000000000..5edb678a96
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/FunctionKLiftCrossBuildSuite.scala
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.arrow.FunctionK
+import cats.syntax.all._
+import org.scalacheck.Prop._
+
+class FunctionKLiftCrossBuildSuite extends CatsSuite {
+ test("lift a function directly") {
+ def headOption[A](list: List[A]): Option[A] = list.headOption
+ val fHeadOption = FunctionK.liftFunction[List, Option](headOption)
+ forAll { (a: List[Int]) =>
+ assert(fHeadOption(a) === a.headOption)
+ }
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/FunctionKSuite.scala b/tests/shared/src/test/scala/cats/tests/FunctionKSuite.scala
similarity index 63%
rename from tests/src/test/scala/cats/tests/FunctionKSuite.scala
rename to tests/shared/src/test/scala/cats/tests/FunctionKSuite.scala
index e47572ab49..826a808b23 100644
--- a/tests/src/test/scala/cats/tests/FunctionKSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/FunctionKSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.arrow.FunctionK
diff --git a/tests/src/test/scala/cats/tests/FunctionSuite.scala b/tests/shared/src/test/scala/cats/tests/FunctionSuite.scala
similarity index 84%
rename from tests/src/test/scala/cats/tests/FunctionSuite.scala
rename to tests/shared/src/test/scala/cats/tests/FunctionSuite.scala
index bf04107700..4be40b0921 100644
--- a/tests/src/test/scala/cats/tests/FunctionSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/FunctionSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{
@@ -15,7 +36,6 @@ import cats.{
}
import cats.arrow.{ArrowChoice, Choice, CommutativeArrow}
import cats.kernel._
-import cats.kernel.laws.HashLaws
import cats.kernel.laws.discipline.{
BandTests,
BoundedSemilatticeTests,
@@ -24,6 +44,7 @@ import cats.kernel.laws.discipline.{
CommutativeSemigroupTests,
EqTests,
GroupTests,
+ HashTests,
MonoidTests,
OrderTests,
PartialOrderTests,
@@ -115,12 +136,7 @@ class FunctionSuite extends CatsSuite {
checkAll("Function0[Grp]", GroupTests[Function0[Grp]].group)
checkAll("Function0[CGrp]", CommutativeGroupTests[Function0[CGrp]].commutativeGroup)
checkAll("Function0[Distributive]", DistributiveTests[Function0].distributive[Int, Int, Int, Id, Function0])
-
- property("Function0[Hsh]") {
- forAll { (x: Function0[Hsh], y: Function0[Hsh]) =>
- HashLaws[Function0[Hsh]].hashCompatibility(x, y)
- }
- }
+ checkAll("Function0[Hsh]", HashTests[Function0[Hsh]].hash)
// Test for Arrow applicative
Applicative[String => *]
@@ -183,4 +199,18 @@ class FunctionSuite extends CatsSuite {
val sumAll = bigList.combineAll(MonoidK[Endo].algebra)
List(1, 1, 1).map(sumAll)
}
+
+ property("Semigroup[Function0[Semi]] is stack safe on combine") {
+ forAll { (f: Function0[Semi]) =>
+ 1.to(50000).foldLeft(f)((acc, _) => Semigroup[Function0[Semi]].combine(acc, f)).apply()
+ true
+ }
+ }
+
+ property("Semigroup[Function1[MiniInt, Semi]] is stack safe on combine") {
+ forAll { (i: MiniInt, f: Function1[MiniInt, Semi]) =>
+ 1.to(50000).foldLeft(f)((acc, _) => Semigroup[Function1[MiniInt, Semi]].combine(acc, f)).apply(i)
+ true
+ }
+ }
}
diff --git a/tests/src/test/scala/cats/tests/FunctorSuite.scala b/tests/shared/src/test/scala/cats/tests/FunctorSuite.scala
similarity index 76%
rename from tests/src/test/scala/cats/tests/FunctorSuite.scala
rename to tests/shared/src/test/scala/cats/tests/FunctorSuite.scala
index c91eb687f7..1c22cc0870 100644
--- a/tests/src/test/scala/cats/tests/FunctorSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/FunctorSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.Functor
diff --git a/tests/shared/src/test/scala/cats/tests/GroupSuite.scala b/tests/shared/src/test/scala/cats/tests/GroupSuite.scala
new file mode 100644
index 0000000000..d6149ca942
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/GroupSuite.scala
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.kernel.Group
+import cats.kernel.laws.discipline.GroupTests
+import cats.syntax.eq._
+
+class GroupSuite extends CatsSuite {
+ test("combine minValue") {
+ assert(Group[Int].combineN(1, Int.MinValue) === (Int.MinValue))
+ }
+
+ test("combine negative") {
+ assert(Group[Int].combineN(1, -1) === -1)
+ assert(Group[Int].combineN(1, -10) === -10)
+ }
+
+ test("companion object syntax") {
+ assert(Group[Int].inverse(1) === -1)
+ assert(Group[Int].remove(1, 2) === -1)
+ }
+
+ checkAll("Int", GroupTests[Int].group)
+// float and double are *not* associative, and ScalaCheck knows
+// checkAll("Double", GroupLaws[Double].group)
+// checkAll("Float", GroupLaws[Float].group)
+ checkAll("Long", GroupTests[Long].group)
+}
diff --git a/tests/shared/src/test/scala/cats/tests/HashSuite.scala b/tests/shared/src/test/scala/cats/tests/HashSuite.scala
new file mode 100644
index 0000000000..c81d78f069
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/HashSuite.scala
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Contravariant, Invariant}
+import cats.kernel.Hash
+import cats.laws.discipline.{DeferTests, MiniInt}
+import cats.laws.discipline.arbitrary._
+import cats.laws.discipline.eq._
+import cats.syntax.hash._
+
+class HashSuite extends CatsSuite {
+
+ {
+ Invariant[Hash]
+ Contravariant[Hash]
+ }
+
+ assert(1.hash == 1.hashCode)
+ assert("ABC".hash == "ABC".hashCode)
+ checkAll("Defer[Hash]", DeferTests[Hash].defer[MiniInt])
+}
diff --git a/tests/shared/src/test/scala/cats/tests/IdSuite.scala b/tests/shared/src/test/scala/cats/tests/IdSuite.scala
new file mode 100644
index 0000000000..7aeb2801fa
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/IdSuite.scala
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.laws.discipline._
+import cats.laws.discipline.arbitrary._
+import cats.syntax.applicative._
+import cats.syntax.eq._
+import cats.{Bimonad, CommutativeMonad, Id, Reducible, Semigroupal, Traverse}
+import org.scalacheck.Prop._
+import cats.Align
+
+class IdSuite extends CatsSuite {
+ implicit val iso: SemigroupalTests.Isomorphisms[Id] =
+ SemigroupalTests.Isomorphisms.invariant[Id]
+
+ checkAll("Id[Int]", BimonadTests[Id].bimonad[Int, Int, Int])
+ checkAll("Bimonad[Id]", SerializableTests.serializable(Bimonad[Id]))
+
+ checkAll("Id[Int]", CommutativeMonadTests[Id].commutativeMonad[Int, Int, Int])
+ checkAll("CommutativeMonad[Id]", SerializableTests.serializable(CommutativeMonad[Id]))
+
+ checkAll("Id[Int]", TraverseTests[Id].traverse[Int, Int, Int, Int, Option, Option])
+ checkAll("Traverse[Id]", SerializableTests.serializable(Traverse[Id]))
+
+ checkAll("Id[Int]", ReducibleTests[Id].reducible[Option, Int, Int])
+ checkAll("Reducible[Id]", SerializableTests.serializable(Reducible[Id]))
+
+ checkAll("Id[Int]", AlignTests[Id].align[Int, Int, Int, Int])
+ checkAll("Align[Id]", SerializableTests.serializable(Align[Id]))
+
+ test("Id#apply") {
+ forAll { (i: Int) =>
+ val id = Id(i)
+ assert(id === (i: Id[Int]))
+ assert(id === i.pure[Id])
+ assert(id === i)
+ }
+ }
+
+ def summonInstances(): Unit = {
+ Semigroupal[Id]
+ ()
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/IdTSuite.scala b/tests/shared/src/test/scala/cats/tests/IdTSuite.scala
similarity index 80%
rename from tests/src/test/scala/cats/tests/IdTSuite.scala
rename to tests/shared/src/test/scala/cats/tests/IdTSuite.scala
index e9be3991cc..64334919bf 100644
--- a/tests/src/test/scala/cats/tests/IdTSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/IdTSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
diff --git a/tests/src/test/scala/cats/tests/IndexedReaderWriterStateTSuite.scala b/tests/shared/src/test/scala/cats/tests/IndexedReaderWriterStateTSuite.scala
similarity index 95%
rename from tests/src/test/scala/cats/tests/IndexedReaderWriterStateTSuite.scala
rename to tests/shared/src/test/scala/cats/tests/IndexedReaderWriterStateTSuite.scala
index 43fd416eed..82224e00ac 100644
--- a/tests/src/test/scala/cats/tests/IndexedReaderWriterStateTSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/IndexedReaderWriterStateTSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
diff --git a/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala b/tests/shared/src/test/scala/cats/tests/IndexedStateTSuite.scala
similarity index 91%
rename from tests/src/test/scala/cats/tests/IndexedStateTSuite.scala
rename to tests/shared/src/test/scala/cats/tests/IndexedStateTSuite.scala
index 151eb00366..04d525c059 100644
--- a/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/IndexedStateTSuite.scala
@@ -1,18 +1,39 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
-import cats.arrow.{Profunctor, Strong}
-import cats.data.{EitherT, IndexedStateT, State, StateT}
-import cats.kernel.Eq
-import cats.laws.discipline._
+import cats.arrow.Profunctor
+import cats.arrow.Strong
+import cats.data.EitherT
+import cats.data.IndexedStateT
+import cats.data.State
+import cats.data.StateT
import cats.laws.discipline.SemigroupalTests.Isomorphisms
-import cats.laws.discipline.eq._
+import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
+import cats.laws.discipline.eq._
import cats.platform.Platform
-import cats.syntax.apply._
-import cats.syntax.flatMap._
-import cats.syntax.traverse._
-import cats.syntax.eq._
+import cats.syntax.all._
import org.scalacheck.Prop._
import org.scalacheck.Test.Parameters
@@ -329,10 +350,9 @@ class IndexedStateTSuite extends CatsSuite {
test("fromState correctly turns State[A, F[B]] into StateT[F, A, B]") {
val state: State[Int, Option[Int]] = add1.map(Some.apply)
- import cats.implicits.catsStdInstancesForOption
forAll { (initial: Int) =>
assert(StateT.fromState(state).run(initial).get === {
- val (s, Some(result)) = state.run(initial).value
+ val (s, Some(result)) = state.run(initial).value: @unchecked // non-exhaustive match warning
(s, result)
})
}
@@ -392,8 +412,9 @@ class IndexedStateTSuite extends CatsSuite {
checkAll("IndexedStateT[ListWrapper, MiniInt, Int, *]",
FunctorFilterTests[IndexedStateT[ListWrapper, MiniInt, Int, *]].functorFilter[Int, Int, Int]
)
- checkAll("FunctorFilter[IndexedStateT[ListWrapper, MiniInt, Int, *]]",
- SerializableTests.serializable(FunctorFilter[IndexedStateT[ListWrapper, MiniInt, Int, *]])
+ checkAll(
+ "FunctorFilter[IndexedStateT[ListWrapper, MiniInt, Int, *]]",
+ SerializableTests.serializable(FunctorFilter[IndexedStateT[ListWrapper, MiniInt, Int, *]])
)
FunctorFilter[IndexedStateT[ListWrapper, String, Int, *]]
@@ -418,8 +439,9 @@ class IndexedStateTSuite extends CatsSuite {
implicit val F: Monad[ListWrapper] = ListWrapper.monad
implicit val FS: Bifunctor[IndexedStateT[ListWrapper, Int, *, *]] = IndexedStateT.catsDataBifunctorForIndexedStateT
- checkAll("IndexedStateT[ListWrapper, MiniInt, String, Int]",
- BifunctorTests[IndexedStateT[ListWrapper, MiniInt, *, *]].bifunctor[String, String, String, Int, Int, Int]
+ checkAll(
+ "IndexedStateT[ListWrapper, MiniInt, String, Int]",
+ BifunctorTests[IndexedStateT[ListWrapper, MiniInt, *, *]].bifunctor[String, String, String, Int, Int, Int]
)
checkAll("Bifunctor[IndexedStateT[ListWrapper, Int, *, *]]",
SerializableTests.serializable(Bifunctor[IndexedStateT[ListWrapper, Int, *, *]])
diff --git a/tests/src/test/scala/cats/tests/InjectKSuite.scala b/tests/shared/src/test/scala/cats/tests/InjectKSuite.scala
similarity index 77%
rename from tests/src/test/scala/cats/tests/InjectKSuite.scala
rename to tests/shared/src/test/scala/cats/tests/InjectKSuite.scala
index 8b068542d2..7a396b38ed 100644
--- a/tests/src/test/scala/cats/tests/InjectKSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/InjectKSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{:<:, Functor, InjectK}
diff --git a/tests/src/test/scala/cats/tests/InjectSuite.scala b/tests/shared/src/test/scala/cats/tests/InjectSuite.scala
similarity index 62%
rename from tests/src/test/scala/cats/tests/InjectSuite.scala
rename to tests/shared/src/test/scala/cats/tests/InjectSuite.scala
index 8362dc891c..15d01b6ff1 100644
--- a/tests/src/test/scala/cats/tests/InjectSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/InjectSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.Inject
diff --git a/tests/src/test/scala/cats/tests/IorSuite.scala b/tests/shared/src/test/scala/cats/tests/IorSuite.scala
similarity index 88%
rename from tests/src/test/scala/cats/tests/IorSuite.scala
rename to tests/shared/src/test/scala/cats/tests/IorSuite.scala
index 84602deea9..fe927fe695 100644
--- a/tests/src/test/scala/cats/tests/IorSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/IorSuite.scala
@@ -1,7 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Bitraverse, MonadError, Semigroupal, Show, Traverse}
-import cats.data.{EitherT, Ior, NonEmptyChain, NonEmptyList, NonEmptySet}
+import cats.data.{EitherT, Ior, NonEmptyChain, NonEmptyList, NonEmptySet, NonEmptyVector}
import cats.kernel.{Eq, Semigroup}
import cats.kernel.laws.discipline.{OrderTests, SemigroupTests}
import cats.laws.discipline.{
@@ -302,8 +323,9 @@ class IorSuite extends CatsSuite {
}
test("toIorNel Both") {
- val ior = Ior.both[String, Int]("oops", 42)
- assert(ior.toIorNel === (Ior.both[NonEmptyList[String], Int](NonEmptyList.one("oops"), 42)))
+ forAll { (x: String, y: Int) =>
+ assert(Ior.both(x, y).toIorNel === (Ior.both[NonEmptyList[String], Int](NonEmptyList.one(x), y)))
+ }
}
test("leftNel") {
diff --git a/tests/src/test/scala/cats/tests/IorTSuite.scala b/tests/shared/src/test/scala/cats/tests/IorTSuite.scala
similarity index 88%
rename from tests/src/test/scala/cats/tests/IorTSuite.scala
rename to tests/shared/src/test/scala/cats/tests/IorTSuite.scala
index 5007cecbec..e1ee78b3e3 100644
--- a/tests/src/test/scala/cats/tests/IorTSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/IorTSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
@@ -102,6 +123,12 @@ class IorTSuite extends CatsSuite {
}
}
+ test("foldF with Id consistent with Ior fold") {
+ forAll { (iort: IorT[Id, String, Int], fa: String => Long, fb: Int => Long, fab: (String, Int) => Long) =>
+ assert(iort.foldF(fa, fb, fab) === (iort.value.fold(fa, fb, fab)))
+ }
+ }
+
test("isLeft with Id consistent with Ior isLeft") {
forAll { (iort: IorT[Id, String, Int]) =>
assert(iort.isLeft === (iort.value.isLeft))
@@ -140,7 +167,16 @@ class IorTSuite extends CatsSuite {
test("getOrElseF with Id consistent with Ior getOrElse") {
forAll { (iort: IorT[Id, String, Int], i: Int) =>
- assert(iort.getOrElseF(i) === (iort.value.getOrElse(i)))
+ assert(iort.getOrElseF(i) === iort.value.getOrElse(i))
+ }
+ }
+
+ test("getOrRaise consistent with IorT.getOrElseF(F.raiseError(e))") {
+ forAll { (iort: IorT[Either[String, *], String, Int], error: String) =>
+ assertEquals(
+ obtained = iort.getOrRaise(error),
+ expected = iort.getOrElseF(Left(error))
+ )
}
}
diff --git a/tests/src/test/scala/cats/tests/IsSuite.scala b/tests/shared/src/test/scala/cats/tests/IsSuite.scala
similarity index 54%
rename from tests/src/test/scala/cats/tests/IsSuite.scala
rename to tests/shared/src/test/scala/cats/tests/IsSuite.scala
index 4c18d75751..19c43ea178 100644
--- a/tests/src/test/scala/cats/tests/IsSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/IsSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.arrow._
diff --git a/tests/src/test/scala/cats/tests/KernelContravariantSuite.scala b/tests/shared/src/test/scala/cats/tests/KernelContravariantSuite.scala
similarity index 60%
rename from tests/src/test/scala/cats/tests/KernelContravariantSuite.scala
rename to tests/shared/src/test/scala/cats/tests/KernelContravariantSuite.scala
index 1d703c81b1..29a82c5341 100644
--- a/tests/src/test/scala/cats/tests/KernelContravariantSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/KernelContravariantSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Contravariant, ContravariantSemigroupal, Invariant, Semigroupal}
diff --git a/tests/src/test/scala/cats/tests/KleisliSuite.scala b/tests/shared/src/test/scala/cats/tests/KleisliSuite.scala
similarity index 89%
rename from tests/src/test/scala/cats/tests/KleisliSuite.scala
rename to tests/shared/src/test/scala/cats/tests/KleisliSuite.scala
index fc618b6467..c7a8ec034c 100644
--- a/tests/src/test/scala/cats/tests/KleisliSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/KleisliSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
@@ -18,9 +39,6 @@ class KleisliSuite extends CatsSuite {
implicit def kleisliEq[F[_], A, B](implicit ev: Eq[A => F[B]]): Eq[Kleisli[F, A, B]] =
Eq.by[Kleisli[F, A, B], A => F[B]](_.run)
- implicit def readerEq[A, B](implicit ev: Eq[A => B]): Eq[Reader[A, B]] =
- kleisliEq
-
implicit val eitherTEq: Eq[EitherT[Kleisli[Option, MiniInt, *], Unit, Int]] =
EitherT.catsDataEqForEitherT[Kleisli[Option, MiniInt, *], Unit, Int]
implicit val eitherTEq2: Eq[EitherT[Reader[MiniInt, *], Unit, Int]] =
@@ -68,6 +86,12 @@ class KleisliSuite extends CatsSuite {
SerializableTests.serializable(CommutativeMonad[Kleisli[Id, Int, *]])
)
+ {
+ implicit val K: Align[Kleisli[Id, MiniInt, *]] = Kleisli.catsDataAlignForKleisli[Id, MiniInt]
+ checkAll("Kleisli[Id, MiniInt, *]", AlignTests[Kleisli[Id, MiniInt, *]].align[Int, Int, Int, Int])
+ }
+ checkAll("Kleisli[Option, MiniInt, *]", AlignTests[Kleisli[Option, MiniInt, *]].align[Int, Int, Int, Int])
+
checkAll("Kleisli[List, *, *]",
ArrowTests[Kleisli[List, *, *]].arrow[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, Boolean]
)
@@ -267,7 +291,7 @@ class KleisliSuite extends CatsSuite {
test("lift") {
val f = Kleisli { (x: Int) =>
- (Some(x + 1): Option[Int])
+ Some(x + 1): Option[Int]
}
val l = f.lift[List]
assert((List(1, 2, 3) >>= l.run) === (List(Some(2), Some(3), Some(4))))
@@ -354,16 +378,16 @@ class KleisliSuite extends CatsSuite {
assertEquals(program.run(A123), List((1, "2", true)))
}
- test("traverse_ doesn't stack overflow") {
+ test("traverseVoid doesn't stack overflow") {
// see: https://github.com/typelevel/cats/issues/3947
- val resL = (1 to 10000).toList.traverse_(_ => Kleisli.liftF[Id, String, Unit](())).run("")
- val resV = (1 to 10000).toVector.traverse_(_ => Kleisli.liftF[Id, String, Unit](())).run("")
- assert(resL == resV)
+ val resL = (1 to 10000).toList.traverseVoid(_ => Kleisli.liftF[Id, String, Unit](())).run("")
+ val resV = (1 to 10000).toVector.traverseVoid(_ => Kleisli.liftF[Id, String, Unit](())).run("")
+ assert(resL === resV)
}
- test("traverse_ doesn't stack overflow with List + Eval") {
+ test("traverseVoid doesn't stack overflow with List + Eval") {
// see: https://github.com/typelevel/cats/issues/3947
- (1 to 10000).toList.traverse_(_ => Kleisli.liftF[Eval, String, Unit](Eval.Unit)).run("").value
+ (1 to 10000).toList.traverseVoid(_ => Kleisli.liftF[Eval, String, Unit](Eval.Unit)).run("").value
}
/**
diff --git a/tests/src/test/scala/cats/tests/ListSuite.scala b/tests/shared/src/test/scala/cats/tests/ListSuite.scala
similarity index 71%
rename from tests/src/test/scala/cats/tests/ListSuite.scala
rename to tests/shared/src/test/scala/cats/tests/ListSuite.scala
index ff17f0ca22..d23c224fdb 100644
--- a/tests/src/test/scala/cats/tests/ListSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/ListSuite.scala
@@ -1,6 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Align, Alternative, CoflatMap, Monad, Semigroupal, Traverse, TraverseFilter}
+import cats.{Align, Alternative, CoflatMap, Eval, Monad, Semigroupal, Traverse, TraverseFilter}
import cats.data.{NonEmptyList, ZipList}
import cats.laws.discipline.{
AlignTests,
@@ -31,7 +52,9 @@ class ListSuite extends CatsSuite {
checkAll("List[Int]", AlternativeTests[List].alternative[Int, Int, Int])
checkAll("Alternative[List]", SerializableTests.serializable(Alternative[List]))
+ // Traverse behaviour discriminates on the Runtime type of the Applicative
checkAll("List[Int] with Option", TraverseTests[List].traverse[Int, Int, Int, Set[Int], Option, Option])
+ checkAll("List[Int] with Eval", TraverseTests[List].traverse[Int, Int, Int, Set[Int], Eval, Eval])
checkAll("Traverse[List]", SerializableTests.serializable(Traverse[List]))
checkAll("List[Int]", MonadTests[List].monad[Int, Int, Int])
diff --git a/tests/src/test/scala/cats/tests/MapSuite.scala b/tests/shared/src/test/scala/cats/tests/MapSuite.scala
similarity index 57%
rename from tests/src/test/scala/cats/tests/MapSuite.scala
rename to tests/shared/src/test/scala/cats/tests/MapSuite.scala
index 29b58941b4..495ff4b015 100644
--- a/tests/src/test/scala/cats/tests/MapSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/MapSuite.scala
@@ -1,6 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Align, FlatMap, FunctorFilter, MonoidK, Semigroupal, Show, UnorderedTraverse}
+import cats.{Align, Eval, FlatMap, FunctorFilter, MonoidK, Semigroupal, Show, UnorderedTraverse}
import cats.arrow.Compose
import cats.kernel.{CommutativeMonoid, Monoid}
import cats.kernel.instances.StaticMethods.wrapMutableMap
@@ -16,8 +37,7 @@ import cats.laws.discipline.{
UnorderedTraverseTests
}
import cats.laws.discipline.arbitrary._
-import cats.syntax.show._
-import cats.syntax.eq._
+import cats.syntax.all._
import org.scalacheck.Prop._
class MapSuite extends CatsSuite {
@@ -28,9 +48,11 @@ class MapSuite extends CatsSuite {
checkAll("Map[Int, Int]", FlatMapTests[Map[Int, *]].flatMap[Int, Int, Int])
checkAll("FlatMap[Map[Int, *]]", SerializableTests.serializable(FlatMap[Map[Int, *]]))
+ // Traverse behaviour discriminates on the Runtime type of the Applicative
checkAll("Map[Int, Int] with Option",
UnorderedTraverseTests[Map[Int, *]].unorderedTraverse[Int, Int, Int, Option, Option]
)
+ checkAll("Map[Int, Int] with Eval", UnorderedTraverseTests[Map[Int, *]].unorderedTraverse[Int, Int, Int, Eval, Eval])
checkAll("UnorderedTraverse[Map[Int, *]]", SerializableTests.serializable(UnorderedTraverse[Map[Int, *]]))
checkAll("Map[Int, Int]", FunctorFilterTests[Map[Int, *]].functorFilter[Int, Int, Int])
@@ -63,4 +85,21 @@ class MapSuite extends CatsSuite {
val m = wrapMutableMap(scala.collection.mutable.Map(1 -> "one", 2 -> "two"))
checkAll("WrappedMutableMap", SerializableTests.serializable(m))
}
+
+ test("unorderedTraverse doesn't stack overflow with tuples") {
+ // https://github.com/typelevel/cats/issues/4461
+ val sum = (1 to 1000000).sum
+ val map = (1 to 1000000).map(x => x -> x).toMap
+ val resL = map.unorderedTraverse(x => (x, x))
+ val resV = (sum, map)
+ assert(resL === resV)
+ }
+
+ test("unorderedTraverse doesn't stack overflow with Options") {
+ // https://github.com/typelevel/cats/issues/4461
+ val map = (1 to 1000000).map(x => x -> x).toMap
+ val resL = map.unorderedTraverse(x => x.some)
+ val resV = Some(map)
+ assert(resL === resV)
+ }
}
diff --git a/tests/src/test/scala/cats/tests/MiniIntSuite.scala b/tests/shared/src/test/scala/cats/tests/MiniIntSuite.scala
similarity index 60%
rename from tests/src/test/scala/cats/tests/MiniIntSuite.scala
rename to tests/shared/src/test/scala/cats/tests/MiniIntSuite.scala
index 200b1eb813..274992e72a 100644
--- a/tests/src/test/scala/cats/tests/MiniIntSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/MiniIntSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.kernel.{BoundedSemilattice, CommutativeGroup, CommutativeMonoid, Hash, Order}
diff --git a/tests/src/test/scala/cats/tests/MonadErrorSuite.scala b/tests/shared/src/test/scala/cats/tests/MonadErrorSuite.scala
similarity index 71%
rename from tests/src/test/scala/cats/tests/MonadErrorSuite.scala
rename to tests/shared/src/test/scala/cats/tests/MonadErrorSuite.scala
index f269cdccea..dd355641f1 100644
--- a/tests/src/test/scala/cats/tests/MonadErrorSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/MonadErrorSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.kernel.Eq
diff --git a/tests/src/test/scala/cats/tests/MonadSuite.scala b/tests/shared/src/test/scala/cats/tests/MonadSuite.scala
similarity index 79%
rename from tests/src/test/scala/cats/tests/MonadSuite.scala
rename to tests/shared/src/test/scala/cats/tests/MonadSuite.scala
index e3f6672634..aa5fa28794 100644
--- a/tests/src/test/scala/cats/tests/MonadSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/MonadSuite.scala
@@ -1,12 +1,33 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Eval, Id, Monad}
import cats.data.{IndexedStateT, StateT}
import cats.syntax.apply._
-import cats.syntax.monad._
-import org.scalacheck.{Arbitrary, Gen}
import cats.syntax.eq._
+import cats.syntax.monad._
+import cats.{Eval, Id, Monad}
import org.scalacheck.Prop._
+import org.scalacheck.{Arbitrary, Gen}
class MonadSuite extends CatsSuite {
implicit val testInstance: Monad[StateT[Id, Int, *]] = IndexedStateT.catsDataMonadForIndexedStateT[Id, Int]
diff --git a/tests/shared/src/test/scala/cats/tests/MonoidSuite.scala b/tests/shared/src/test/scala/cats/tests/MonoidSuite.scala
new file mode 100644
index 0000000000..bfa0e6a6fd
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/MonoidSuite.scala
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Invariant, InvariantSemigroupal}
+import cats.kernel.Monoid
+import cats.syntax.eq._
+
+class MonoidSuite extends CatsSuite {
+ {
+ Invariant[Monoid]
+ InvariantSemigroupal[Monoid]
+ }
+
+ test("companion object syntax") {
+ assert(Monoid.empty[Int] === 0)
+ assert(Monoid.isEmpty(1) === false)
+ assert(Monoid.isEmpty(0) === true)
+ }
+}
+
+object MonoidSuite {
+ def summonInstance(): Unit = {
+ Invariant[Monoid]
+ ()
+ }
+
+}
diff --git a/tests/src/test/scala/cats/tests/NestedSuite.scala b/tests/shared/src/test/scala/cats/tests/NestedSuite.scala
similarity index 90%
rename from tests/src/test/scala/cats/tests/NestedSuite.scala
rename to tests/shared/src/test/scala/cats/tests/NestedSuite.scala
index 041b742561..3459b1f479 100644
--- a/tests/src/test/scala/cats/tests/NestedSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/NestedSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
@@ -219,8 +240,9 @@ class NestedSuite extends CatsSuite {
checkAll("Nested[NonEmptyList, OneAnd[ListWrapper, *], *]",
ReducibleTests[Nested[NonEmptyList, OneAnd[ListWrapper, *], *]].reducible[Option, Int, Int]
)
- checkAll("Reducible[Nested[NonEmptyList, OneAnd[ListWrapper, *], *]]",
- SerializableTests.serializable(Reducible[Nested[NonEmptyList, OneAnd[ListWrapper, *], *]])
+ checkAll(
+ "Reducible[Nested[NonEmptyList, OneAnd[ListWrapper, *], *]]",
+ SerializableTests.serializable(Reducible[Nested[NonEmptyList, OneAnd[ListWrapper, *], *]])
)
}
diff --git a/tests/shared/src/test/scala/cats/tests/NonEmptyAlternativeSuite.scala b/tests/shared/src/test/scala/cats/tests/NonEmptyAlternativeSuite.scala
new file mode 100644
index 0000000000..d86c0b23b7
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/NonEmptyAlternativeSuite.scala
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.NonEmptyAlternative
+import cats.laws.discipline.NonEmptyAlternativeTests
+
+class NonEmptyAlternativeSuite extends CatsSuite {
+ implicit val listWrapperNeAlternative: NonEmptyAlternative[ListWrapper] = ListWrapper.nonEmptyAlternative
+
+ checkAll("Option[Int]", NonEmptyAlternativeTests[Option].nonEmptyAlternative[Int, Int, Int])
+ checkAll("List[Int]", NonEmptyAlternativeTests[List].nonEmptyAlternative[Int, Int, Int])
+ checkAll("ListWrapper[List[Int]]", NonEmptyAlternativeTests[ListWrapper].nonEmptyAlternative[Int, Int, Int])
+ checkAll(
+ "compose ListWrapper[List[Int]]",
+ NonEmptyAlternativeTests.composed[ListWrapper, List].nonEmptyAlternative[Int, Int, Int]
+ )
+ checkAll(
+ "compose List[ListWrapper[Int]]",
+ NonEmptyAlternativeTests.composed[List, ListWrapper].nonEmptyAlternative[Int, Int, Int]
+ )
+ checkAll(
+ "compose ListWrapper[ListWrapper[Int]]",
+ NonEmptyAlternativeTests.composed[ListWrapper, ListWrapper].nonEmptyAlternative[Int, Int, Int]
+ )
+}
diff --git a/tests/src/test/scala/cats/tests/NonEmptyChainSuite.scala b/tests/shared/src/test/scala/cats/tests/NonEmptyChainSuite.scala
similarity index 79%
rename from tests/src/test/scala/cats/tests/NonEmptyChainSuite.scala
rename to tests/shared/src/test/scala/cats/tests/NonEmptyChainSuite.scala
index b85adadd01..5fd0fadf74 100644
--- a/tests/src/test/scala/cats/tests/NonEmptyChainSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/NonEmptyChainSuite.scala
@@ -1,21 +1,39 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Align, Bimonad, SemigroupK, Show, Traverse}
-import cats.data.{Chain, NonEmptyChain, NonEmptyChainOps}
-import cats.kernel.{Eq, Order, PartialOrder, Semigroup}
-import cats.kernel.laws.discipline.{EqTests, OrderTests, PartialOrderTests, SemigroupTests}
-import cats.laws.discipline.{
- AlignTests,
- BimonadTests,
- NonEmptyTraverseTests,
- SemigroupKTests,
- SerializableTests,
- ShortCircuitingTests
-}
+import cats._
+import cats.data.Chain
+import cats.data.NonEmptyChain
+import cats.data.NonEmptyChainOps
+import cats.kernel.laws.discipline.EqTests
+import cats.kernel.laws.discipline.OrderTests
+import cats.kernel.laws.discipline.PartialOrderTests
+import cats.kernel.laws.discipline.SemigroupTests
+import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
import cats.syntax.either._
-import cats.syntax.foldable._
import cats.syntax.eq._
+import cats.syntax.foldable._
import org.scalacheck.Prop._
class NonEmptyChainSuite extends NonEmptyCollectionSuite[Chain, NonEmptyChain, NonEmptyChainOps] {
@@ -23,8 +41,8 @@ class NonEmptyChainSuite extends NonEmptyCollectionSuite[Chain, NonEmptyChain, N
protected def underlyingToList[A](underlying: Chain[A]): List[A] = underlying.toList
protected def toNonEmptyCollection[A](nea: NonEmptyChain[A]): NonEmptyChainOps[A] = nea
- checkAll("NonEmptyChain[Int]", SemigroupKTests[NonEmptyChain].semigroupK[Int])
- checkAll("SemigroupK[NonEmptyChain]", SerializableTests.serializable(SemigroupK[NonEmptyChain]))
+ checkAll("NonEmptyChain[Int]", NonEmptyAlternativeTests[NonEmptyChain].nonEmptyAlternative[Int, Int, Int])
+ checkAll("NonEmptyAlternative[NonEmptyChain]", SerializableTests.serializable(NonEmptyAlternative[NonEmptyChain]))
checkAll("NonEmptyChain[Int] with Option",
NonEmptyTraverseTests[NonEmptyChain].nonEmptyTraverse[Option, Int, Int, Int, Int, Option, Option]
@@ -185,6 +203,12 @@ class NonEmptyChainSuite extends NonEmptyCollectionSuite[Chain, NonEmptyChain, N
}
}
+ test("NonEmptyChain#distinctBy is consistent with List#distinctBy") {
+ forAll { (ci: NonEmptyChain[Int], f: Int => String) =>
+ assert(ci.distinctBy(f).toList === (ci.toList.distinctBy(f)))
+ }
+ }
+
test("NonEmptyChain#distinct is consistent with List#distinct") {
forAll { (ci: NonEmptyChain[Int]) =>
assert(ci.distinct.toList === (ci.toList.distinct))
diff --git a/tests/src/test/scala/cats/tests/NonEmptyCollectionSuite.scala b/tests/shared/src/test/scala/cats/tests/NonEmptyCollectionSuite.scala
similarity index 80%
rename from tests/src/test/scala/cats/tests/NonEmptyCollectionSuite.scala
rename to tests/shared/src/test/scala/cats/tests/NonEmptyCollectionSuite.scala
index 7b55bd95f0..b7a3bdb3f4 100644
--- a/tests/src/test/scala/cats/tests/NonEmptyCollectionSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/NonEmptyCollectionSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.data.NonEmptyCollection
@@ -82,6 +103,12 @@ abstract class NonEmptyCollectionSuite[U[+_], NE[+_], NEC[x] <: NonEmptyCollecti
}
}
+ test("collectFirst is consistent with iterator.toList.collectFirst") {
+ forAll { (is: NE[Int], pf: PartialFunction[Int, String]) =>
+ assert(is.collectFirst(pf) === is.iterator.toList.collectFirst(pf))
+ }
+ }
+
test("find is consistent with iterator.toList.find") {
forAll { (is: NE[Int], pred: Int => Boolean) =>
assert(is.find(pred) === (is.iterator.toList.find(pred)))
diff --git a/tests/src/test/scala/cats/tests/NonEmptyListSuite.scala b/tests/shared/src/test/scala/cats/tests/NonEmptyListSuite.scala
similarity index 87%
rename from tests/src/test/scala/cats/tests/NonEmptyListSuite.scala
rename to tests/shared/src/test/scala/cats/tests/NonEmptyListSuite.scala
index 2ee7a35033..a72995abf8 100644
--- a/tests/src/test/scala/cats/tests/NonEmptyListSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/NonEmptyListSuite.scala
@@ -1,29 +1,48 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Align, Bimonad, Eval, NonEmptyTraverse, Now, Reducible, SemigroupK, Show}
-import cats.data.{NonEmptyList, NonEmptyMap, NonEmptySet, NonEmptyVector}
+import cats._
+import cats.data.NonEmptyList
import cats.data.NonEmptyList.ZipNonEmptyList
-import cats.kernel.{Eq, Order, PartialOrder, Semigroup}
-import cats.kernel.laws.discipline.{EqTests, OrderTests, PartialOrderTests, SemigroupTests}
+import cats.data.NonEmptyMap
+import cats.data.NonEmptySet
+import cats.data.NonEmptyVector
+import cats.kernel.laws.discipline.EqTests
+import cats.kernel.laws.discipline.OrderTests
+import cats.kernel.laws.discipline.PartialOrderTests
+import cats.kernel.laws.discipline.SemigroupTests
+import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
-import cats.laws.discipline.{
- AlignTests,
- BimonadTests,
- CommutativeApplyTests,
- NonEmptyTraverseTests,
- ReducibleTests,
- SemigroupKTests,
- SerializableTests,
- ShortCircuitingTests
-}
+import cats.syntax.eq._
import cats.syntax.foldable._
import cats.syntax.reducible._
import cats.syntax.show._
-import scala.collection.immutable.{SortedMap, SortedSet}
-import cats.syntax.eq._
import org.scalacheck.Prop._
import org.scalacheck.Test.Parameters
+import scala.collection.immutable.SortedMap
+import scala.collection.immutable.SortedSet
+
class NonEmptyListSuite extends NonEmptyCollectionSuite[List, NonEmptyList, NonEmptyList] {
protected def toList[A](value: NonEmptyList[A]): List[A] = value.toList
protected def underlyingToList[A](underlying: List[A]): List[A] = underlying
@@ -43,8 +62,8 @@ class NonEmptyListSuite extends NonEmptyCollectionSuite[List, NonEmptyList, NonE
checkAll("NonEmptyList[Int]", ReducibleTests[NonEmptyList].reducible[Option, Int, Int])
checkAll("Reducible[NonEmptyList]", SerializableTests.serializable(Reducible[NonEmptyList]))
- checkAll("NonEmptyList[Int]", SemigroupKTests[NonEmptyList].semigroupK[Int])
- checkAll("SemigroupK[NonEmptyList[A]]", SerializableTests.serializable(SemigroupK[NonEmptyList]))
+ checkAll("NonEmptyList[Int]", NonEmptyAlternativeTests[NonEmptyList].nonEmptyAlternative[Int, Int, Int])
+ checkAll("NonEmptyAlternative[NonEmptyList[A]]", SerializableTests.serializable(NonEmptyAlternative[NonEmptyList]))
checkAll("NonEmptyList[Int]", SemigroupTests[NonEmptyList[Int]].semigroup)
checkAll("Semigroup[NonEmptyList[Int]]", SerializableTests.serializable(Semigroup[NonEmptyList[Int]]))
@@ -264,12 +283,25 @@ class NonEmptyListSuite extends NonEmptyCollectionSuite[List, NonEmptyList, NonE
}
}
+ test("++: consistent with List#:::") {
+ forAll { (nel: NonEmptyList[Int], i: List[Int]) =>
+ assert((i ++: nel).toList === (i ::: nel.toList))
+ assert(nel.prependList(i).toList === (i ::: nel.toList))
+ }
+ }
+
test("NonEmptyList#distinct is consistent with List#distinct") {
forAll { (nel: NonEmptyList[Int]) =>
assert(nel.distinct.toList === (nel.toList.distinct))
}
}
+ test("NonEmptyList#distinctBy is consistent with List#distinctBy") {
+ forAll { (nel: NonEmptyList[Int], f: Int => String) =>
+ assert(nel.distinctBy(f).toList === (nel.toList.distinctBy(f)))
+ }
+ }
+
test("NonEmptyList#reverse is consistent with List#reverse") {
forAll { (nel: NonEmptyList[Int]) =>
assert(nel.reverse.toList === (nel.toList.reverse))
@@ -357,6 +389,7 @@ class NonEmptyListSuite extends NonEmptyCollectionSuite[List, NonEmptyList, NonE
forAll { (nel: NonEmptyList[Int], l: List[Int], n: Int) =>
assert((nel ++ l).toList === (nel.toList ::: l))
assert(nel.concat(l).toList === (nel.toList ::: l))
+ assert(nel.appendList(l).toList === (nel.toList ::: l))
assert(nel.concatNel(NonEmptyList(n, l)).toList === (nel.toList ::: (n :: l)))
}
}
diff --git a/tests/src/test/scala/cats/tests/NonEmptyMapSuite.scala b/tests/shared/src/test/scala/cats/tests/NonEmptyMapSuite.scala
similarity index 89%
rename from tests/src/test/scala/cats/tests/NonEmptyMapSuite.scala
rename to tests/shared/src/test/scala/cats/tests/NonEmptyMapSuite.scala
index 9d9f8be7f1..2738204776 100644
--- a/tests/src/test/scala/cats/tests/NonEmptyMapSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/NonEmptyMapSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Align, Eval, Foldable, Now, Semigroup, SemigroupK, Show}
diff --git a/tests/shared/src/test/scala/cats/tests/NonEmptySeqSuite.scala b/tests/shared/src/test/scala/cats/tests/NonEmptySeqSuite.scala
new file mode 100644
index 0000000000..36899298bc
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/NonEmptySeqSuite.scala
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats._
+import cats.data.NonEmptySeq
+import cats.kernel.laws.discipline.SemigroupTests
+import cats.laws.discipline._
+import cats.laws.discipline.arbitrary._
+import cats.syntax.all._
+import org.scalacheck.Prop._
+
+import scala.collection.immutable.Seq
+
+class NonEmptySeqSuite extends NonEmptyCollectionSuite[Seq, NonEmptySeq, NonEmptySeq] {
+ override protected def toList[A](value: NonEmptySeq[A]): List[A] = value.toList
+ override protected def underlyingToList[A](underlying: Seq[A]): List[A] = underlying.toList
+ override protected def toNonEmptyCollection[A](value: NonEmptySeq[A]): NonEmptySeq[A] = value
+
+ checkAll(
+ "NonEmptySeq[Int] with Option",
+ NonEmptyTraverseTests[NonEmptySeq].nonEmptyTraverse[Option, Int, Int, Int, Int, Option, Option]
+ )
+ checkAll("NonEmptyTraverse[NonEmptySeq[A]]", SerializableTests.serializable(NonEmptyTraverse[NonEmptySeq]))
+
+ checkAll("NonEmptySeq[Int]", ReducibleTests[NonEmptySeq].reducible[Option, Int, Int])
+ checkAll("Reducible[NonEmptySeq]", SerializableTests.serializable(Reducible[NonEmptySeq]))
+
+ checkAll("NonEmptySeq[Int]", NonEmptyAlternativeTests[NonEmptySeq].nonEmptyAlternative[Int, Int, Int])
+ checkAll("NonEmptyAlternative[NonEmptySeq[A]]", SerializableTests.serializable(NonEmptyAlternative[NonEmptySeq]))
+
+ checkAll("NonEmptySeq[Int]", SemigroupTests[NonEmptySeq[Int]].semigroup)
+ checkAll("Semigroup[NonEmptySeq[Int]]", SerializableTests.serializable(Semigroup[NonEmptySeq[Int]]))
+
+ checkAll("NonEmptySeq[Int]", BimonadTests[NonEmptySeq].bimonad[Int, Int, Int])
+ checkAll("Bimonad[NonEmptySeq]", SerializableTests.serializable(Bimonad[NonEmptySeq]))
+
+ checkAll("NonEmptySeq[Int]", AlignTests[NonEmptySeq].align[Int, Int, Int, Int])
+ checkAll("Align[NonEmptySeq]", SerializableTests.serializable(Align[NonEmptySeq]))
+
+ checkAll("NonEmptySeq[Int]", ShortCircuitingTests[NonEmptySeq].foldable[Int])
+ checkAll("NonEmptySeq[Int]", ShortCircuitingTests[NonEmptySeq].traverse[Int])
+ checkAll("NonEmptySeq[Int]", ShortCircuitingTests[NonEmptySeq].nonEmptyTraverse[Int])
+
+ test("neSeq => Seq => neSeq returns original neSeq")(
+ forAll { (fa: NonEmptySeq[Int]) =>
+ assert(fa.toSeq.toNeSeq == Some(fa))
+ }
+ )
+
+ test("NonEmptySeq#concat/appendSeq is consistent with Seq#++")(
+ forAll { (fa: NonEmptySeq[Int], fb: Seq[Int]) =>
+ assert((fa ++ fb).toSeq == fa.toSeq ++ fb)
+ assert(fa.concat(fb).toSeq == fa.toSeq ++ fb)
+ assert(fa.appendSeq(fb).toSeq == fa.toSeq ++ fb)
+ }
+ )
+
+ test("NonEmptySeq#concatNeSeq is consistent with concat")(
+ forAll { (fa: NonEmptySeq[Int], fb: NonEmptySeq[Int]) =>
+ assert(fa.concatNeSeq(fb).toSeq == fa.concat(fb.toSeq).toSeq)
+ }
+ )
+
+ test("toNeSeq on empty Seq returns None") {
+ assert(Seq.empty[Int].toNeSeq == None)
+ }
+
+ test("NonEmptySeq#zip is consistent with Seq#zip") {
+ forAll { (a: NonEmptySeq[Int], b: NonEmptySeq[Int]) =>
+ assert(a.zip(b).toSeq === (a.toSeq.zip(b.toSeq)))
+ }
+ }
+
+ test("NonEmptySeq#distinct is consistent with List#distinct") {
+ forAll { (nes: NonEmptySeq[Int]) =>
+ assert(nes.distinct.toList === (nes.toList.distinct))
+ }
+ }
+
+ test("NonEmptySeq#distinctBy is consistent with List#distinctBy") {
+ forAll { (nes: NonEmptySeq[Int], f: Int => String) =>
+ assert(nes.distinctBy(f).toList === (nes.toList.distinctBy(f)))
+ }
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/NonEmptySetSuite.scala b/tests/shared/src/test/scala/cats/tests/NonEmptySetSuite.scala
similarity index 88%
rename from tests/src/test/scala/cats/tests/NonEmptySetSuite.scala
rename to tests/shared/src/test/scala/cats/tests/NonEmptySetSuite.scala
index c8920f428f..5841978266 100644
--- a/tests/src/test/scala/cats/tests/NonEmptySetSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/NonEmptySetSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Eval, Now, Reducible, SemigroupK, Show}
diff --git a/tests/src/test/scala/cats/tests/NonEmptyVectorSuite.scala b/tests/shared/src/test/scala/cats/tests/NonEmptyVectorSuite.scala
similarity index 87%
rename from tests/src/test/scala/cats/tests/NonEmptyVectorSuite.scala
rename to tests/shared/src/test/scala/cats/tests/NonEmptyVectorSuite.scala
index 3590f7bf58..0656ca9d94 100644
--- a/tests/src/test/scala/cats/tests/NonEmptyVectorSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/NonEmptyVectorSuite.scala
@@ -1,48 +1,47 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{
- Align,
- Bimonad,
- CommutativeApply,
- Comonad,
- Eval,
- Foldable,
- Functor,
- Monad,
- NonEmptyTraverse,
- Now,
- Reducible,
- SemigroupK,
- Show,
- Traverse
-}
+import cats._
import cats.data.NonEmptyVector
import cats.data.NonEmptyVector.ZipNonEmptyVector
-import cats.kernel.Semigroup
import cats.kernel.instances.order.catsKernelOrderingForOrder
-import cats.kernel.laws.discipline.{EqTests, SemigroupTests}
-import cats.laws.discipline.{
- AlignTests,
- BimonadTests,
- CommutativeApplyTests,
- FoldableTests,
- NonEmptyTraverseTests,
- ReducibleTests,
- SemigroupKTests,
- SerializableTests,
- ShortCircuitingTests
-}
+import cats.kernel.laws.discipline.EqTests
+import cats.kernel.laws.discipline.HashTests
+import cats.kernel.laws.discipline.OrderTests
+import cats.kernel.laws.discipline.SemigroupTests
+import cats.kernel.laws.discipline.PartialOrderTests
+import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
import cats.platform.Platform
+import cats.syntax.eq._
import cats.syntax.foldable._
import cats.syntax.reducible._
import cats.syntax.show._
-
-import scala.util.Properties
-import cats.syntax.eq._
import org.scalacheck.Prop._
import org.scalacheck.Test.Parameters
+import scala.util.Properties
+
class NonEmptyVectorSuite extends NonEmptyCollectionSuite[Vector, NonEmptyVector, NonEmptyVector] {
protected def toList[A](value: NonEmptyVector[A]): List[A] = value.toList
protected def underlyingToList[A](underlying: Vector[A]): List[A] = underlying.toList
@@ -53,6 +52,9 @@ class NonEmptyVectorSuite extends NonEmptyCollectionSuite[Vector, NonEmptyVector
Parameters.default.withMinSuccessfulTests(20).withMaxSize(Parameters.default.minSize + 5)
checkAll("NonEmptyVector[Int]", EqTests[NonEmptyVector[Int]].eqv)
+ checkAll("NonEmptyVector[Int]", HashTests[NonEmptyVector[Int]].hash)
+ checkAll("NonEmptyVector[Int]", OrderTests[NonEmptyVector[Int]].order)
+ checkAll("NonEmptyVector[Int]", PartialOrderTests[NonEmptyVector[Int]].partialOrder)
checkAll("NonEmptyVector[Int] with Option",
NonEmptyTraverseTests[NonEmptyVector].nonEmptyTraverse[Option, Int, Int, Int, Int, Option, Option]
@@ -64,10 +66,10 @@ class NonEmptyVectorSuite extends NonEmptyCollectionSuite[Vector, NonEmptyVector
// Test instances that have more general constraints
- checkAll("NonEmptyVector[Int]", SemigroupKTests[NonEmptyVector].semigroupK[Int])
- checkAll("NonEmptyVector[Int]", SemigroupTests[NonEmptyVector[Int]].semigroup)
- checkAll("SemigroupK[NonEmptyVector]", SerializableTests.serializable(SemigroupK[NonEmptyVector]))
+ checkAll("NonEmptyVector[Int]", NonEmptyAlternativeTests[NonEmptyVector].nonEmptyAlternative[Int, Int, Int])
checkAll("Semigroup[NonEmptyVector[Int]]", SerializableTests.serializable(Semigroup[NonEmptyVector[Int]]))
+ checkAll("NonEmptyVector[Int]", SemigroupTests[NonEmptyVector[Int]].semigroup)
+ checkAll("NonEmptyAlternative[NonEmptyVector]", SerializableTests.serializable(NonEmptyAlternative[NonEmptyVector]))
checkAll("NonEmptyVector[Int]", FoldableTests[NonEmptyVector].foldable[Int, Int])
checkAll("Foldable[NonEmptyVector]", SerializableTests.serializable(Foldable[NonEmptyVector]))
@@ -235,6 +237,12 @@ class NonEmptyVectorSuite extends NonEmptyCollectionSuite[Vector, NonEmptyVector
}
}
+ test("appendVector is consistent with concat") {
+ forAll { (nonEmptyVector: NonEmptyVector[Int], vector: Vector[Int]) =>
+ assert(nonEmptyVector.appendVector(vector) === nonEmptyVector.concat(vector))
+ }
+ }
+
test(":+ is consistent with concat") {
forAll { (nonEmptyVector: NonEmptyVector[Int], i: Int) =>
assert(nonEmptyVector :+ i === (nonEmptyVector.concat(Vector(i))))
@@ -357,6 +365,12 @@ class NonEmptyVectorSuite extends NonEmptyCollectionSuite[Vector, NonEmptyVector
assert(compileErrors("val bad: NonEmptyVector[Int] = NonEmptyVector(Vector.empty[Int])").nonEmpty)
}
+ test("NonEmptyVector#distinctBy is consistent with Vector#distinctBy") {
+ forAll { (nonEmptyVector: NonEmptyVector[Int], f: Int => String) =>
+ assert(nonEmptyVector.distinctBy(f).toVector === (nonEmptyVector.toVector.distinctBy(f)))
+ }
+ }
+
test("NonEmptyVector#distinct is consistent with Vector#distinct") {
forAll { (nonEmptyVector: NonEmptyVector[Int]) =>
assert(nonEmptyVector.distinct.toVector === (nonEmptyVector.toVector.distinct))
diff --git a/tests/shared/src/test/scala/cats/tests/OneAndSuite.scala b/tests/shared/src/test/scala/cats/tests/OneAndSuite.scala
new file mode 100644
index 0000000000..d7b57e889b
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/OneAndSuite.scala
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Alternative
+import cats.Applicative
+import cats.Foldable
+import cats.Functor
+import cats.Monad
+import cats.SemigroupK
+import cats.Traverse
+import cats.data.OneAnd
+import cats.kernel.Eq
+import cats.kernel.Order
+import cats.kernel.PartialOrder
+import cats.kernel.laws.discipline.EqTests
+import cats.kernel.laws.discipline.OrderTests
+import cats.kernel.laws.discipline.PartialOrderTests
+import cats.laws.discipline.SemigroupalTests.Isomorphisms
+import cats.laws.discipline._
+import cats.laws.discipline.arbitrary._
+import cats.syntax.foldable._
+import cats.syntax.order._
+import org.scalacheck.Prop._
+import org.scalacheck.Test.Parameters
+
+class OneAndSuite extends CatsSuite {
+ // Lots of collections here.. telling ScalaCheck to calm down a bit
+ implicit override val scalaCheckTestParameters: Parameters =
+ Parameters.default.withMinSuccessfulTests(20).withMaxSize(Parameters.default.minSize + 5)
+
+ // Test kernel instances
+ {
+ import Helpers.Eqed
+
+ checkAll("OneAnd[F, A]", EqTests[OneAnd[ListWrapper, Eqed]].eqv)
+ checkAll("Eq[OneAnd[F, A]]", SerializableTests.serializable(Eq[OneAnd[ListWrapper, Eqed]]))
+
+ property("Eq[OneAnd[F, A]]: must be consistent with Eq[Tuple2[A, F[A]]]") {
+ forAll { (x: OneAnd[ListWrapper, Eqed], y: OneAnd[ListWrapper, Eqed]) =>
+ assertEquals(x.eqv(y), (x.head, x.tail).eqv((y.head, y.tail)))
+ }
+ }
+ }
+ {
+ import Helpers.POrd
+
+ implicit val partialOrder: PartialOrder[ListWrapper[POrd]] = ListWrapper.partialOrder
+ checkAll("OneAnd[F, A]", PartialOrderTests[OneAnd[ListWrapper, POrd]].partialOrder)
+ checkAll("PartialOrder[OneAnd[F, A]]", SerializableTests.serializable(PartialOrder[OneAnd[ListWrapper, POrd]]))
+
+ property("PartialOrder[OneAnd[F, A]]: must be consistent with PartialOrder[Tuple2[A, F[A]]]") {
+ forAll { (x: OneAnd[ListWrapper, POrd], y: OneAnd[ListWrapper, POrd]) =>
+ // `NaN` cannot be compared directly; hence using `partialComparison` instead of `partialCompare`.
+ assertEquals(x.partialComparison(y), (x.head, x.tail).partialComparison((y.head, y.tail)))
+ }
+ }
+ }
+ {
+ import Helpers.Ord
+
+ implicit val order: Order[ListWrapper[Ord]] = ListWrapper.order
+ checkAll("OneAnd[F, A]", OrderTests[OneAnd[ListWrapper, Ord]].order)
+ checkAll("Order[OneAnd[F, A]]", SerializableTests.serializable(Order[OneAnd[ListWrapper, Ord]]))
+
+ property("Order[OneAnd[F, A]]: must be consistent with Order[Tuple2[A, F[A]]]") {
+ forAll { (x: OneAnd[ListWrapper, Ord], y: OneAnd[ListWrapper, Ord]) =>
+ assertEquals(x.compare(y), (x.head, x.tail).compare((y.head, y.tail)))
+ }
+ }
+ }
+
+ {
+ implicit val traverse: Traverse[OneAnd[ListWrapper, *]] = OneAnd.catsDataTraverseForOneAnd(ListWrapper.traverse)
+ checkAll("OneAnd[ListWrapper, Int] with Option",
+ TraverseTests[OneAnd[ListWrapper, *]].traverse[Int, Int, Int, Int, Option, Option]
+ )
+ checkAll("Traverse[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Traverse[OneAnd[ListWrapper, *]]))
+ }
+
+ implicit val iso: Isomorphisms[OneAnd[ListWrapper, *]] =
+ Isomorphisms.invariant[OneAnd[ListWrapper, *]](OneAnd.catsDataFunctorForOneAnd(ListWrapper.functor))
+
+ // Test instances that have more general constraints
+ {
+ implicit val monad: Monad[ListWrapper] = ListWrapper.monad
+ implicit val alt: Alternative[ListWrapper] = ListWrapper.alternative
+ checkAll("OneAnd[ListWrapper, Int]", MonadTests[OneAnd[ListWrapper, *]].monad[Int, Int, Int])
+ checkAll("MonadTests[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Monad[OneAnd[ListWrapper, *]]))
+ }
+
+ {
+ implicit val alternative: Alternative[ListWrapper] = ListWrapper.alternative
+ checkAll("OneAnd[ListWrapper, Int]", ApplicativeTests[OneAnd[ListWrapper, *]].applicative[Int, Int, Int])
+ checkAll("Applicative[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Applicative[OneAnd[ListWrapper, *]]))
+ }
+
+ {
+ implicit val functor: Functor[ListWrapper] = ListWrapper.functor
+ checkAll("OneAnd[ListWrapper, Int]", FunctorTests[OneAnd[ListWrapper, *]].functor[Int, Int, Int])
+ checkAll("Functor[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Functor[OneAnd[ListWrapper, *]]))
+ }
+
+ {
+ implicit val alternative: Alternative[ListWrapper] = ListWrapper.alternative
+ checkAll("OneAnd[ListWrapper, Int]", SemigroupKTests[OneAnd[ListWrapper, *]].semigroupK[Int])
+ checkAll("SemigroupK[OneAnd[ListWrapper, A]]", SerializableTests.serializable(SemigroupK[OneAnd[ListWrapper, *]]))
+ }
+
+ {
+ implicit val foldable: Foldable[ListWrapper] = ListWrapper.foldable
+ checkAll("OneAnd[ListWrapper, Int]", FoldableTests[OneAnd[ListWrapper, *]].foldable[Int, Int])
+ checkAll("Foldable[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Foldable[OneAnd[ListWrapper, *]]))
+ }
+
+ test("size is consistent with toList.size") {
+ forAll { (oa: OneAnd[Vector, Int]) =>
+ assert(oa.size === (oa.toList.size.toLong))
+ }
+ }
+
+}
diff --git a/tests/src/test/scala/cats/tests/OpSuite.scala b/tests/shared/src/test/scala/cats/tests/OpSuite.scala
similarity index 54%
rename from tests/src/test/scala/cats/tests/OpSuite.scala
rename to tests/shared/src/test/scala/cats/tests/OpSuite.scala
index ea3937f748..aa273e7b7b 100644
--- a/tests/src/test/scala/cats/tests/OpSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/OpSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.arrow._
diff --git a/tests/src/test/scala/cats/tests/OptionSuite.scala b/tests/shared/src/test/scala/cats/tests/OptionSuite.scala
similarity index 78%
rename from tests/src/test/scala/cats/tests/OptionSuite.scala
rename to tests/shared/src/test/scala/cats/tests/OptionSuite.scala
index aa247585df..4fca282522 100644
--- a/tests/src/test/scala/cats/tests/OptionSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/OptionSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.laws.discipline._
diff --git a/tests/src/test/scala/cats/tests/OptionTSuite.scala b/tests/shared/src/test/scala/cats/tests/OptionTSuite.scala
similarity index 87%
rename from tests/src/test/scala/cats/tests/OptionTSuite.scala
rename to tests/shared/src/test/scala/cats/tests/OptionTSuite.scala
index 2d46259a24..bb6ae51483 100644
--- a/tests/src/test/scala/cats/tests/OptionTSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/OptionTSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
@@ -282,6 +303,16 @@ class OptionTSuite extends CatsSuite {
)
}
}
+
+ test("OptionT[Try, A].getOrRaise consistent with OptionT.getOrElseF(F.raiseError(e))") {
+ forAll { (o: Either[String, Option[Int]], error: String) =>
+ assertEquals(
+ obtained = OptionT[Either[String, *], Int](o).getOrRaise(error),
+ expected = OptionT[Either[String, *], Int](o).getOrElseF(Left(error))
+ )
+ }
+ }
+
test("OptionT[Id, A].collect consistent with Option.collect") {
forAll { (o: Option[Int], f: Int => Option[String]) =>
val p = Function.unlift(f)
@@ -301,6 +332,12 @@ class OptionTSuite extends CatsSuite {
}
}
+ test("OptionT[Id, A].filterF consistent with Option.filter") {
+ forAll { (o: Option[Int], f: Int => Boolean) =>
+ assert(o.filter(f) === (OptionT[Id, Int](o).filterF(f).value))
+ }
+ }
+
test("OptionT[Id, A].withFilter consistent with Option.withFilter") {
forAll { (o: Option[Int], f: Int => Boolean) =>
assert((for { x <- o if f(x) } yield x) === ((for { x <- OptionT[Id, Int](o) if f(x) } yield x).value))
@@ -347,6 +384,21 @@ class OptionTSuite extends CatsSuite {
}
}
+ test("OptionT.whenM[Id, A] consistent with Option.when") {
+ // Option.when is inlined here because it is not available before Scala 2.13
+ def when[A]: (Boolean, A) => Option[A] = (c: Boolean, a: A) => if (c) Some(a) else None
+
+ forAll { (i: Int, b: Boolean) =>
+ assert(OptionT.whenM[Id, Int](b)(i).value === (when(b, i)))
+ }
+ }
+
+ test("OptionT.whenF and OptionT.whenM consistent") {
+ forAll { (li: List[Int], bs: List[Boolean]) =>
+ assert(bs.flatMap(OptionT.whenF(_)(li).value) === OptionT.whenM(bs)(li).value)
+ }
+ }
+
test("OptionT.whenK and OptionT.whenF consistent") {
forAll { (li: List[Int], b: Boolean) =>
assert(IdT(li).mapK(OptionT.whenK(b)).value === (OptionT.whenF(b)(li)))
@@ -369,6 +421,21 @@ class OptionTSuite extends CatsSuite {
}
}
+ test("OptionT.unlessM[Id, A] consistent with Option.unless") {
+ // Option.unless is inlined here because it is not available before Scala 2.13
+ def unless[A]: (Boolean, A) => Option[A] = (c: Boolean, a: A) => if (!c) Some(a) else None
+
+ forAll { (i: Int, b: Boolean) =>
+ assert(OptionT.unlessM[Id, Int](b)(i).value === (unless(b, i)))
+ }
+ }
+
+ test("OptionT.unlessF and OptionT.unlessM consistent") {
+ forAll { (li: List[Int], bs: List[Boolean]) =>
+ assert(bs.flatMap(OptionT.unlessF(_)(li).value) === OptionT.unlessM(bs)(li).value)
+ }
+ }
+
test("OptionT.unlessK and OptionT.unlessF consistent") {
forAll { (li: List[Int], b: Boolean) =>
assert(IdT(li).mapK(OptionT.unlessK(b)).value === (OptionT.unlessF(b)(li)))
diff --git a/tests/shared/src/test/scala/cats/tests/OptionWrapper.scala b/tests/shared/src/test/scala/cats/tests/OptionWrapper.scala
new file mode 100644
index 0000000000..5114dacc1b
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/OptionWrapper.scala
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Functor
+import cats.laws.discipline.ExhaustiveCheck
+import org.scalacheck.{Arbitrary, Cogen}
+import org.scalacheck.Arbitrary.arbitrary
+
+/**
+ * Similar to [[ListWrapper]], but using `Option` instead of `List` limits the size of the structure, which can be
+ * useful for limiting the space of test values to generate.
+ */
+final case class OptionWrapper[A](option: Option[A]) extends AnyVal
+
+object OptionWrapper {
+ val functor: Functor[OptionWrapper] = new Functor[OptionWrapper] {
+ def map[A, B](fa: OptionWrapper[A])(f: A => B) = OptionWrapper(fa.option.map(f))
+ }
+
+ implicit def optionWrapperArbitrary[A: Arbitrary]: Arbitrary[OptionWrapper[A]] =
+ Arbitrary(arbitrary[Option[A]].map(OptionWrapper.apply))
+
+ implicit def optionWrapperCogen[A: Cogen]: Cogen[OptionWrapper[A]] =
+ Cogen[Option[A]].contramap(_.option)
+
+ implicit def catsLawsExhaustiveCheckForOptionWrapper[A](implicit
+ A: ExhaustiveCheck[A]
+ ): ExhaustiveCheck[OptionWrapper[A]] =
+ ExhaustiveCheck.instance(ExhaustiveCheck[Option[A]].allValues.map(OptionWrapper(_)))
+}
diff --git a/tests/src/test/scala/cats/tests/OrderSuite.scala b/tests/shared/src/test/scala/cats/tests/OrderSuite.scala
similarity index 62%
rename from tests/src/test/scala/cats/tests/OrderSuite.scala
rename to tests/shared/src/test/scala/cats/tests/OrderSuite.scala
index 114f3e3312..ec093bea93 100644
--- a/tests/src/test/scala/cats/tests/OrderSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/OrderSuite.scala
@@ -1,13 +1,34 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Contravariant, ContravariantMonoidal, Invariant}
import cats.kernel.{Order, PartialOrder}
import cats.kernel.laws.discipline.{OrderTests, SerializableTests}
-import cats.laws.discipline.{ContravariantMonoidalTests, MiniInt}
+import cats.laws.discipline.{ContravariantMonoidalTests, DeferTests, MiniInt}
import cats.laws.discipline.arbitrary._
import cats.laws.discipline.eq._
import cats.tests.Helpers.Ord
-import cats.implicits._
+import cats.syntax.all._
import org.scalacheck.Prop._
class OrderSuite extends CatsSuite {
@@ -24,6 +45,7 @@ class OrderSuite extends CatsSuite {
checkAll("Order", ContravariantMonoidalTests[Order].contravariantMonoidal[MiniInt, Boolean, Boolean])
checkAll("ContravariantMonoidal[Order]", SerializableTests.serializable(ContravariantMonoidal[Order]))
+ checkAll("Defer[Order]", DeferTests[Order].defer[MiniInt])
test("order ops syntax") {
forAll { (i: Ord, j: Ord) =>
diff --git a/tests/shared/src/test/scala/cats/tests/OrderingSuite.scala b/tests/shared/src/test/scala/cats/tests/OrderingSuite.scala
new file mode 100644
index 0000000000..b06b5d7dd3
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/OrderingSuite.scala
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Contravariant, ContravariantMonoidal, ContravariantSemigroupal, Invariant, Semigroupal}
+import cats.laws.discipline.arbitrary._
+import cats.laws.discipline._
+import cats.laws.discipline.eq._
+
+class OrderingSuite extends CatsSuite {
+
+ Invariant[Ordering]
+ Contravariant[Ordering]
+ Semigroupal[Ordering]
+ ContravariantSemigroupal[Ordering]
+ ContravariantMonoidal[Ordering]
+
+ checkAll("Contravariant[Ordering]", ContravariantTests[Ordering].contravariant[MiniInt, Int, Boolean])
+ checkAll("Semigroupal[Ordering]", SemigroupalTests[Ordering].semigroupal[MiniInt, Boolean, Boolean])
+ checkAll("ContravariantMonoidal[Ordering]",
+ ContravariantMonoidalTests[Ordering].contravariantMonoidal[MiniInt, Boolean, Boolean]
+ )
+ checkAll("ContravariantMonoidal[Ordering]", SerializableTests.serializable(ContravariantMonoidal[Ordering]))
+ checkAll("Defer[Ordering]", DeferTests[Ordering].defer[MiniInt])
+}
diff --git a/tests/src/test/scala/cats/tests/ParallelSuite.scala b/tests/shared/src/test/scala/cats/tests/ParallelSuite.scala
similarity index 83%
rename from tests/src/test/scala/cats/tests/ParallelSuite.scala
rename to tests/shared/src/test/scala/cats/tests/ParallelSuite.scala
index 8c707bd1cd..4dc50a6d20 100644
--- a/tests/src/test/scala/cats/tests/ParallelSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/ParallelSuite.scala
@@ -1,20 +1,46 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
-import cats.data._
import cats.data.NonEmptyList.ZipNonEmptyList
+import cats.data._
import cats.kernel.compat.scalaVersionSpecific._
-import cats.laws.discipline.{ApplicativeErrorTests, MiniInt, NonEmptyParallelTests, ParallelTests, SerializableTests}
-import cats.laws.discipline.eq._
+import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
-import cats.implicits._
-import org.scalacheck.{Arbitrary, Gen}
+import cats.laws.discipline.eq._
+import cats.syntax.all._
+import org.scalacheck.Arbitrary
+import org.scalacheck.Gen
+import org.scalacheck.Prop._
import scala.collection.immutable.SortedSet
-import org.scalacheck.Prop._
@suppressUnusedImportWarningForScalaVersionSpecific
-class ParallelSuite extends CatsSuite with ApplicativeErrorForEitherTest with ScalaVersionSpecificParallelSuite {
+class ParallelSuite
+ extends CatsSuite
+ with ApplicativeErrorForEitherTest
+ with ScalaVersionSpecificParallelSuite
+ with ParallelSuiteStreamSpecific {
test("ParSequence Either should accumulate errors") {
forAll { (es: List[Either[String, Int]]) =>
@@ -52,24 +78,24 @@ class ParallelSuite extends CatsSuite with ApplicativeErrorForEitherTest with Sc
}
}
- test("ParTraverse_ identity should be equivalent to parSequence_") {
+ test("ParTraverseVoid identity should be equivalent to parSequenceVoid") {
forAll { (es: SortedSet[Either[String, Int]]) =>
- assert(Parallel.parTraverse_(es)(identity) === (Parallel.parSequence_[SortedSet, Either[String, *], Int](es)))
+ assert(Parallel.parTraverseVoid(es)(identity) === Parallel.parSequenceVoid[SortedSet, Either[String, *], Int](es))
}
}
- test("ParTraverse_ syntax should be equivalent to Parallel.parTraverse_") {
+ test("ParTraverseVoid syntax should be equivalent to Parallel.parTraverseVoid") {
forAll { (es: SortedSet[Either[String, Int]]) =>
assert(
- Parallel.parTraverse_[SortedSet, Either[String, *], Either[String, Int], Int](es)(identity) === (es
- .parTraverse_(identity))
+ Parallel.parTraverseVoid[SortedSet, Either[String, *], Either[String, Int], Int](es)(identity) ===
+ es.parTraverseVoid(identity)
)
}
}
- test("ParSequence_ syntax should be equivalent to Parallel.parSequence_") {
+ test("ParSequenceVoid syntax should be equivalent to Parallel.parSequenceVoid") {
forAll { (es: SortedSet[Either[String, Int]]) =>
- assert(Parallel.parSequence_[SortedSet, Either[String, *], Int](es) === (es.parSequence_))
+ assert(Parallel.parSequenceVoid[SortedSet, Either[String, *], Int](es) === es.parSequenceVoid)
}
}
@@ -79,9 +105,9 @@ class ParallelSuite extends CatsSuite with ApplicativeErrorForEitherTest with Sc
}
}
- test("ParNonEmptyTraverse_ identity should be equivalent to parNonEmptySequence_") {
+ test("ParNonEmptyTraverseVoid identity should be equivalent to parNonEmptySequenceVoid") {
forAll { (es: NonEmptyList[Either[String, Int]]) =>
- assert(Parallel.parNonEmptyTraverse_(es)(identity) === (Parallel.parNonEmptySequence_(es)))
+ assert(Parallel.parNonEmptyTraverseVoid(es)(identity) === Parallel.parNonEmptySequenceVoid(es))
}
}
@@ -284,12 +310,25 @@ class ParallelSuite extends CatsSuite with ApplicativeErrorForEitherTest with Sc
}
}
+ test("ParReplicateA_ should be equivalent to fill parSequenceVoid") {
+ forAll(Gen.choose(1, 20), Arbitrary.arbitrary[Either[String, String]]) {
+ (repetitions: Int, e: Either[String, String]) =>
+ assert(Parallel.parReplicateA_(repetitions, e) === Parallel.parSequenceVoid(List.fill(repetitions)(e)))
+ }
+ }
+
test("ParReplicateA 2 should be equivalent to parMap2 List") {
forAll { (e: Either[String, String]) =>
assert(Parallel.parReplicateA(2, e) === Parallel.parMap2(e, e)((s1, s2) => List(s1, s2)))
}
}
+ test("ParReplicateA_ 2 should be equivalent to parMap2.void List") {
+ forAll { (e: Either[String, String]) =>
+ assert(Parallel.parReplicateA_(2, e) === Parallel.parMap2(e, e)((s1, s2) => List(s1, s2)).void)
+ }
+ }
+
test("Kleisli with Either should accumulate errors") {
val k1: Kleisli[Either[String, *], String, Int] = Kleisli(s => Right(s.length))
val k2: Kleisli[Either[String, *], String, Int] = Kleisli(s => Left("Boo"))
@@ -351,19 +390,35 @@ class ParallelSuite extends CatsSuite with ApplicativeErrorForEitherTest with Sc
}
}
- test("ParMap over Stream should be consistent with zip") {
- forAll { (as: Stream[Int], bs: Stream[Int], cs: Stream[Int]) =>
- val zipped = as
- .zip(bs)
- .map { case (a, b) =>
- a + b
- }
- .zip(cs)
- .map { case (a, b) =>
- a + b
- }
+ test("ParFlatMapN over List should be consistent with parMapN flatten") {
+ forAll { (as: List[Int], bs: List[Int], cs: List[Int], mf: (Int, Int, Int) => List[Int]) =>
+ assert((as, bs, cs).parFlatMapN(mf) == (as, bs, cs).parMapN(mf).flatten)
+ }
+ }
- assert((as, bs, cs).parMapN(_ + _ + _) === zipped)
+ test("ParFlatMapN over NonEmptyList should be consistent with parMapN flatten") {
+ forAll {
+ (as: NonEmptyList[Int], bs: NonEmptyList[Int], cs: NonEmptyList[Int], mf: (Int, Int, Int) => NonEmptyList[Int]) =>
+ assert((as, bs, cs).parFlatMapN(mf) == (as, bs, cs).parMapN(mf).flatten)
+ }
+ }
+
+ test("ParFlatMap over List should be consistent with flatmap") {
+ forAll { (as: List[Int], mf: Int => List[Int]) =>
+ assert(Tuple1(as).parFlatMap(mf) == Tuple1(as).flatMap(mf))
+ }
+ }
+
+ test("ParFlatMap over NonEmptyList should be consistent with flatmap") {
+ forAll { (as: NonEmptyList[Int], mf: Int => NonEmptyList[Int]) =>
+ assert(Tuple1(as).parFlatMap(mf) == Tuple1(as).flatMap(mf))
+ }
+ }
+
+ test("ParMapN over f should be consistent with parFlatMapN over f lifted in List") {
+ forAll { (as: List[Int], bs: List[Int], f: (Int, Int) => Int) =>
+ val mf: (Int, Int) => List[Int] = (a, b) => f(a, b).pure[List]
+ assert((as, bs).parMapN(f) == (as, bs).parFlatMapN(mf))
}
}
@@ -391,12 +446,6 @@ class ParallelSuite extends CatsSuite with ApplicativeErrorForEitherTest with Sc
}
}
- test("ParTupled of Stream should be consistent with ParMap of Tuple.apply") {
- forAll { (fa: Stream[Int], fb: Stream[Int], fc: Stream[Int], fd: Stream[Int]) =>
- assert((fa, fb, fc, fd).parTupled === ((fa, fb, fc, fd).parMapN(Tuple4.apply)))
- }
- }
-
test("ParTupled of List should be consistent with zip") {
forAll { (fa: List[Int], fb: List[Int], fc: List[Int], fd: List[Int]) =>
assert((fa, fb, fc, fd).parTupled === fa.zip(fb).zip(fc).zip(fd).map { case (((a, b), c), d) => (a, b, c, d) })
@@ -409,12 +458,6 @@ class ParallelSuite extends CatsSuite with ApplicativeErrorForEitherTest with Sc
}
}
- test("ParTupled of Stream should be consistent with zip") {
- forAll { (fa: Stream[Int], fb: Stream[Int], fc: Stream[Int], fd: Stream[Int]) =>
- assert((fa, fb, fc, fd).parTupled === fa.zip(fb).zip(fc).zip(fd).map { case (((a, b), c), d) => (a, b, c, d) })
- }
- }
-
test("IorT leverages parallel effect instances when it exists") {
case class Marker(value: String) extends java.lang.Exception("marker") {
override def fillInStackTrace: Throwable = null
@@ -536,16 +579,11 @@ class ParallelSuite extends CatsSuite with ApplicativeErrorForEitherTest with Sc
)
checkAll("NonEmptyParallel[Vector]", NonEmptyParallelTests[Vector].nonEmptyParallel[Int, String])
checkAll("NonEmptyParallel[List]", NonEmptyParallelTests[List].nonEmptyParallel[Int, String])
- // Can't test Parallel here, as Applicative[ZipStream].pure doesn't terminate
- checkAll("Parallel[Stream]", NonEmptyParallelTests[Stream].nonEmptyParallel[Int, String])
checkAll("NonEmptyParallel[NonEmptyVector]", NonEmptyParallelTests[NonEmptyVector].nonEmptyParallel[Int, String])
checkAll("NonEmptyParallel[NonEmptyList]", NonEmptyParallelTests[NonEmptyList].nonEmptyParallel[Int, String])
- // TODO this doesn't infer?
- checkAll("Parallel[NonEmptyStream]", ParallelTests[NonEmptyStream, OneAnd[ZipStream, *]].parallel[Int, String])
-
checkAll("Parallel[Id]", ParallelTests[Id].parallel[Int, String])
checkAll("NonEmptyParallel[NonEmptyList]", SerializableTests.serializable(NonEmptyParallel[NonEmptyList]))
@@ -573,6 +611,44 @@ class ParallelSuite extends CatsSuite with ApplicativeErrorForEitherTest with Sc
val p1: NonEmptyParallel.Aux[Either[String, *], Validated[String, *]] = NonEmptyParallel[Either[String, *]]
val p2: NonEmptyParallel.Aux[NonEmptyList, ZipNonEmptyList] = NonEmptyParallel[NonEmptyList]
}
+}
+
+@annotation.nowarn("cat=deprecation")
+sealed trait ParallelSuiteStreamSpecific { self: ParallelSuite =>
+
+ test("ParMap over Stream should be consistent with zip") {
+ forAll { (as: Stream[Int], bs: Stream[Int], cs: Stream[Int]) =>
+ val zipped = as
+ .zip(bs)
+ .map { case (a, b) =>
+ a + b
+ }
+ .zip(cs)
+ .map { case (a, b) =>
+ a + b
+ }
+
+ assert((as, bs, cs).parMapN(_ + _ + _) === zipped)
+ }
+ }
+
+ test("ParTupled of Stream should be consistent with ParMap of Tuple.apply") {
+ forAll { (fa: Stream[Int], fb: Stream[Int], fc: Stream[Int], fd: Stream[Int]) =>
+ assert((fa, fb, fc, fd).parTupled === ((fa, fb, fc, fd).parMapN(Tuple4.apply)))
+ }
+ }
+
+ test("ParTupled of Stream should be consistent with zip") {
+ forAll { (fa: Stream[Int], fb: Stream[Int], fc: Stream[Int], fd: Stream[Int]) =>
+ assert((fa, fb, fc, fd).parTupled === fa.zip(fb).zip(fc).zip(fd).map { case (((a, b), c), d) => (a, b, c, d) })
+ }
+ }
+
+ // Can't test Parallel here, as Applicative[ZipStream].pure doesn't terminate
+ checkAll("Parallel[Stream]", NonEmptyParallelTests[Stream].nonEmptyParallel[Int, String])
+
+ // TODO this doesn't infer?
+ checkAll("Parallel[NonEmptyStream]", ParallelTests[NonEmptyStream, OneAnd[ZipStream, *]].parallel[Int, String])
test("Parallel.apply should return an appropriately typed instance given both type parameters") {
val p1: Parallel.Aux[Either[String, *], Validated[String, *]] = Parallel[Either[String, *], Validated[String, *]]
diff --git a/tests/shared/src/test/scala/cats/tests/PartialFunctionSuite.scala b/tests/shared/src/test/scala/cats/tests/PartialFunctionSuite.scala
new file mode 100644
index 0000000000..f364507802
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/PartialFunctionSuite.scala
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+import cats.arrow.{ArrowChoice, CommutativeArrow}
+import cats.kernel.laws.discipline.SerializableTests
+import cats.laws.discipline.arbitrary._
+import cats.laws.discipline.eq._
+import cats.laws.discipline.{ArrowChoiceTests, CommutativeArrowTests, MiniInt}
+
+class PartialFunctionSuite extends CatsSuite {
+
+ checkAll("ArrowChoice[PartialFunction]", SerializableTests.serializable(ArrowChoice[PartialFunction]))
+
+ checkAll("PartialFunction",
+ ArrowChoiceTests[PartialFunction].arrowChoice[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, MiniInt]
+ )
+
+ checkAll("CommutativeArrow[PartialFunction]", SerializableTests.serializable(CommutativeArrow[PartialFunction]))
+ checkAll(
+ "PartialFunction",
+ CommutativeArrowTests[PartialFunction].commutativeArrow[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, MiniInt]
+ )
+
+}
diff --git a/tests/src/test/scala/cats/tests/PartialOrderSuite.scala b/tests/shared/src/test/scala/cats/tests/PartialOrderSuite.scala
similarity index 65%
rename from tests/src/test/scala/cats/tests/PartialOrderSuite.scala
rename to tests/shared/src/test/scala/cats/tests/PartialOrderSuite.scala
index d7e4114ce5..5fffe1c874 100644
--- a/tests/src/test/scala/cats/tests/PartialOrderSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/PartialOrderSuite.scala
@@ -1,12 +1,33 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Contravariant, ContravariantMonoidal, Invariant}
import cats.kernel.{Order, PartialOrder}
import cats.kernel.laws.discipline.SerializableTests
-import cats.laws.discipline.{ContravariantMonoidalTests, MiniInt}
+import cats.laws.discipline.{ContravariantMonoidalTests, DeferTests, MiniInt}
import cats.laws.discipline.arbitrary._
import cats.laws.discipline.eq._
-import cats.implicits._
+import cats.syntax.all._
import cats.tests.Helpers.POrd
import org.scalacheck.Prop._
@@ -26,6 +47,7 @@ class PartialOrderSuite extends CatsSuite {
checkAll("PartialOrder", ContravariantMonoidalTests[PartialOrder].contravariantMonoidal[MiniInt, Boolean, Boolean])
checkAll("ContravariantMonoidal[PartialOrder]", SerializableTests.serializable(ContravariantMonoidal[PartialOrder]))
+ checkAll("Defer[PartialOrder]", DeferTests[PartialOrder].defer[MiniInt])
test("companion object syntax") {
forAll { (i: Int, j: Int) =>
diff --git a/tests/shared/src/test/scala/cats/tests/PartialOrderingSuite.scala b/tests/shared/src/test/scala/cats/tests/PartialOrderingSuite.scala
new file mode 100644
index 0000000000..7b302ee958
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/PartialOrderingSuite.scala
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Contravariant, ContravariantMonoidal, ContravariantSemigroupal, Invariant, Semigroupal}
+import cats.laws.discipline.arbitrary._
+import cats.laws.discipline._
+import cats.laws.discipline.eq._
+
+class PartialOrderingSuite extends CatsSuite {
+
+ Invariant[PartialOrdering]
+ Contravariant[PartialOrdering]
+ Semigroupal[PartialOrdering]
+ ContravariantSemigroupal[PartialOrdering]
+
+ checkAll("Contravariant[PartialOrdering]", ContravariantTests[PartialOrdering].contravariant[MiniInt, Int, Boolean])
+ checkAll("Semigroupal[PartialOrdering]", SemigroupalTests[PartialOrdering].semigroupal[MiniInt, Boolean, Boolean])
+ checkAll("Contravariant[PartialOrdering]", SerializableTests.serializable(Contravariant[PartialOrdering]))
+
+ checkAll("PartialOrdering[Int]",
+ ContravariantMonoidalTests[PartialOrdering].contravariantMonoidal[MiniInt, Boolean, Boolean]
+ )
+ checkAll("ContravariantMonoidal[PartialOrdering]",
+ SerializableTests.serializable(ContravariantMonoidal[PartialOrdering])
+ )
+ checkAll("Defer[PartialOrdering]", DeferTests[PartialOrdering].defer[MiniInt])
+}
diff --git a/tests/src/test/scala/cats/tests/QueueSuite.scala b/tests/shared/src/test/scala/cats/tests/QueueSuite.scala
similarity index 56%
rename from tests/src/test/scala/cats/tests/QueueSuite.scala
rename to tests/shared/src/test/scala/cats/tests/QueueSuite.scala
index 28ac4c6660..40ae944294 100644
--- a/tests/src/test/scala/cats/tests/QueueSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/QueueSuite.scala
@@ -1,6 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Alternative, CoflatMap, Monad, Semigroupal, Traverse, TraverseFilter}
+import cats.{Alternative, CoflatMap, Eval, Monad, Semigroupal, Traverse, TraverseFilter}
import cats.laws.discipline.{
AlternativeTests,
CoflatMapTests,
@@ -11,6 +32,7 @@ import cats.laws.discipline.{
TraverseFilterTests,
TraverseTests
}
+import cats.laws.discipline.arbitrary._
import cats.syntax.show._
import scala.collection.immutable.Queue
import cats.syntax.eq._
@@ -28,7 +50,9 @@ class QueueSuite extends CatsSuite {
checkAll("Queue[Int]", MonadTests[Queue].monad[Int, Int, Int])
checkAll("Monad[Queue]", SerializableTests.serializable(Monad[Queue]))
+ // Traverse behaviour discriminates on the Runtime type of the Applicative
checkAll("Queue[Int] with Option", TraverseTests[Queue].traverse[Int, Int, Int, Set[Int], Option, Option])
+ checkAll("Queue[Int] with Eval", TraverseTests[Queue].traverse[Int, Int, Int, Set[Int], Eval, Eval])
checkAll("Traverse[Queue]", SerializableTests.serializable(Traverse[Queue]))
checkAll("Queue[Int]", TraverseFilterTests[Queue].traverseFilter[Int, Int, Int])
diff --git a/tests/src/test/scala/cats/tests/ReducibleSuite.scala b/tests/shared/src/test/scala/cats/tests/ReducibleSuite.scala
similarity index 81%
rename from tests/src/test/scala/cats/tests/ReducibleSuite.scala
rename to tests/shared/src/test/scala/cats/tests/ReducibleSuite.scala
index ac2793461e..a17a44e443 100644
--- a/tests/src/test/scala/cats/tests/ReducibleSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/ReducibleSuite.scala
@@ -1,20 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Eval, NonEmptyReducible, Now, Reducible}
+import cats._
import cats.data.NonEmptyList
-import cats.kernel.Eq
-import cats.syntax.either._
-import cats.syntax.foldable._
-import cats.syntax.list._
-import cats.syntax.option._
-import cats.syntax.reducible._
+import cats.syntax.all._
import org.scalacheck.Arbitrary
+import org.scalacheck.Prop._
import scala.collection.mutable
-import cats.syntax.eq._
-import org.scalacheck.Prop._
-class ReducibleSuiteAdditional extends CatsSuite {
+class ReducibleSuiteAdditional extends CatsSuite with ReducibleSuiteAdditionalStreamSpecific {
// exists method written in terms of reduceRightTo
def contains[F[_]: Reducible, A: Eq](as: F[A], goal: A): Eval[Boolean] =
@@ -49,11 +64,11 @@ class ReducibleSuiteAdditional extends CatsSuite {
assert(R.reduceLeftTo(names)(_.length)((sum, s) => s.length + sum) === totalLength)
assert(R.reduceMap(names)(_.length) === totalLength)
val sumLeftM = R.reduceLeftM(names)(Some(_): Option[String]) { (acc, x) =>
- (Some(acc + x): Option[String])
+ Some(acc + x): Option[String]
}
assert(sumLeftM == Some("AaronBettyCalvinDeirdra"))
val sumMapM = R.reduceMapM(names) { x =>
- (Some(x): Option[String])
+ Some(x): Option[String]
}
assert(sumMapM == Some("AaronBettyCalvinDeirdra"))
val isNotCalvin: String => Option[String] =
@@ -69,7 +84,10 @@ class ReducibleSuiteAdditional extends CatsSuite {
val large = NonEmptyList(1, (2 to 10000).toList)
assert(contains(large, 10000).value)
}
+}
+@annotation.nowarn("cat=deprecation")
+sealed trait ReducibleSuiteAdditionalStreamSpecific { self: ReducibleSuiteAdditional =>
// A simple non-empty stream with lazy `foldRight` and `reduceRightTo` implementations.
case class NES[A](h: A, t: Stream[A]) {
def toStream: Stream[A] = h #:: t
@@ -79,14 +97,14 @@ class ReducibleSuiteAdditional extends CatsSuite {
implicit val nesReducible: Reducible[NES] = new Reducible[NES] {
def foldLeft[A, B](fa: NES[A], b: B)(f: (B, A) => B): B = fa.toStream.foldLeft(b)(f)
def foldRight[A, B](fa: NES[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
- fa match {
+ (fa: @unchecked) match {
case NES(h, Stream()) => f(h, lb)
case NES(h, th #:: tt) => f(h, Eval.defer(foldRight(NES(th, tt), lb)(f)))
}
def reduceLeftTo[A, B](fa: NES[A])(f: A => B)(g: (B, A) => B): B = fa.t.foldLeft(f(fa.h))(g)
def reduceRightTo[A, B](fa: NES[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] =
- fa match {
+ (fa: @unchecked) match {
case NES(h, Stream()) => Eval.now(f(h))
case NES(h, th #:: tt) => g(h, Eval.defer(reduceRightTo(NES(th, tt))(f)(g)))
}
@@ -216,11 +234,11 @@ abstract class ReducibleSuite[F[_]: Reducible](name: String)(implicit
assert(out.toList === List(2, 4, 6, 9))
}
- test(s"Reducible[$name].nonEmptyTraverse_ can breakout") {
+ test(s"Reducible[$name].nonEmptyTraverseVoid can breakout") {
val notAllEven = fromValues(2, 4, 6, 9, 10, 12, 14)
val out = mutable.ListBuffer[Int]()
- notAllEven.nonEmptyTraverse_ { a => out += a; if (a % 2 == 0) Some(a) else None }
+ notAllEven.nonEmptyTraverseVoid { a => out += a; if (a % 2 == 0) Some(a) else None }
assert(out.toList === List(2, 4, 6, 9))
}
diff --git a/tests/src/test/scala/cats/tests/RegressionSuite.scala b/tests/shared/src/test/scala/cats/tests/RegressionSuite.scala
similarity index 71%
rename from tests/src/test/scala/cats/tests/RegressionSuite.scala
rename to tests/shared/src/test/scala/cats/tests/RegressionSuite.scala
index 2edf022df1..2d852e2cb3 100644
--- a/tests/src/test/scala/cats/tests/RegressionSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/RegressionSuite.scala
@@ -1,17 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Apply, Monad, MonadError, StackSafeMonad, Traverse}
-import cats.data.{Const, NonEmptyList, StateT}
-import cats.kernel.Eq
+import cats._
+import cats.data.Const
+import cats.data.NonEmptyList
+import cats.data.StateT
import cats.kernel.compat.scalaVersionSpecific._
-import cats.syntax.applicativeError._
-import cats.syntax.either._
-import cats.syntax.foldable._
-import cats.syntax.monadError._
-import cats.syntax.traverse._
-import scala.collection.mutable
+import cats.syntax.all._
+
import scala.collection.immutable.SortedMap
-import cats.syntax.eq._
+import scala.collection.mutable
@suppressUnusedImportWarningForScalaVersionSpecific
class RegressionSuite extends CatsSuite with ScalaVersionSpecificRegressionSuite {
@@ -123,7 +141,11 @@ class RegressionSuite extends CatsSuite with ScalaVersionSpecificRegressionSuite
// shouldn't have ever evaluated validate(8)
checkAndResetCount(3)
- assert(Stream(1, 2, 6, 8).traverse(validate) === (Either.left("6 is greater than 5")))
+ {
+ @annotation.nowarn("cat=deprecation")
+ val obtained = Stream(1, 2, 6, 8).traverse(validate).void
+ assert(obtained === Either.left("6 is greater than 5"))
+ }
checkAndResetCount(3)
type StringMap[A] = SortedMap[String, A]
@@ -140,19 +162,23 @@ class RegressionSuite extends CatsSuite with ScalaVersionSpecificRegressionSuite
assert(Vector(1, 2, 6, 8).traverse(validate) === (Either.left("6 is greater than 5")))
checkAndResetCount(3)
- assert(List(1, 2, 6, 8).traverse_(validate) === (Either.left("6 is greater than 5")))
+ assert(List(1, 2, 6, 8).traverseVoid(validate) === Either.left("6 is greater than 5"))
checkAndResetCount(3)
- assert(Stream(1, 2, 6, 8).traverse_(validate) === (Either.left("6 is greater than 5")))
+ {
+ @annotation.nowarn("cat=deprecation")
+ val obtained = Stream(1, 2, 6, 8).traverseVoid(validate)
+ assert(obtained === Either.left("6 is greater than 5"))
+ }
checkAndResetCount(3)
- assert(Vector(1, 2, 6, 8).traverse_(validate) === (Either.left("6 is greater than 5")))
+ assert(Vector(1, 2, 6, 8).traverseVoid(validate) === Either.left("6 is greater than 5"))
checkAndResetCount(3)
- assert(NonEmptyList.of(1, 2, 6, 7, 8).traverse_(validate) === (Either.left("6 is greater than 5")))
+ assert(NonEmptyList.of(1, 2, 6, 7, 8).traverseVoid(validate) === Either.left("6 is greater than 5"))
checkAndResetCount(3)
- assert(NonEmptyList.of(6, 7, 8).traverse_(validate) === (Either.left("6 is greater than 5")))
+ assert(NonEmptyList.of(6, 7, 8).traverseVoid(validate) === Either.left("6 is greater than 5"))
checkAndResetCount(1)
}
diff --git a/tests/src/test/scala/cats/tests/RepresentableStoreSuite.scala b/tests/shared/src/test/scala/cats/tests/RepresentableStoreSuite.scala
similarity index 67%
rename from tests/src/test/scala/cats/tests/RepresentableStoreSuite.scala
rename to tests/shared/src/test/scala/cats/tests/RepresentableStoreSuite.scala
index d784e81452..408a67eb97 100644
--- a/tests/src/test/scala/cats/tests/RepresentableStoreSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/RepresentableStoreSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.Comonad
@@ -17,10 +38,6 @@ class RepresentableStoreSuite extends CatsSuite {
{
implicit val pairComonad: Comonad[RepresentableStore[λ[P => (P, P)], Boolean, *]] =
RepresentableStore.catsDataRepresentableStoreComonad[λ[P => (P, P)], Boolean]
- implicit val arbStore: Arbitrary[RepresentableStore[λ[P => (P, P)], Boolean, Int]] =
- catsLawsArbitraryForRepresentableStore[λ[P => (P, P)], Boolean, Int]
- implicit val cogenStore: Cogen[RepresentableStore[λ[P => (P, P)], Boolean, Int]] =
- catsLawsCogenForRepresentableStore[λ[P => (P, P)], Boolean, Int]
implicit val eqStore: Eq[RepresentableStore[λ[P => (P, P)], Boolean, Int]] =
cats.laws.discipline.eq.catsLawsEqForRepresentableStore[λ[P => (P, P)], Boolean, Int]
implicit val eqStoreStore
diff --git a/tests/src/test/scala/cats/tests/RepresentableStoreTSuite.scala b/tests/shared/src/test/scala/cats/tests/RepresentableStoreTSuite.scala
similarity index 67%
rename from tests/src/test/scala/cats/tests/RepresentableStoreTSuite.scala
rename to tests/shared/src/test/scala/cats/tests/RepresentableStoreTSuite.scala
index 623054e7d5..4a40bff74a 100644
--- a/tests/src/test/scala/cats/tests/RepresentableStoreTSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/RepresentableStoreTSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
diff --git a/tests/src/test/scala/cats/tests/RepresentableSuite.scala b/tests/shared/src/test/scala/cats/tests/RepresentableSuite.scala
similarity index 79%
rename from tests/src/test/scala/cats/tests/RepresentableSuite.scala
rename to tests/shared/src/test/scala/cats/tests/RepresentableSuite.scala
index 2842ae7e63..13c1792aaa 100644
--- a/tests/src/test/scala/cats/tests/RepresentableSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/RepresentableSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
diff --git a/tests/shared/src/test/scala/cats/tests/SemigroupKSuite.scala b/tests/shared/src/test/scala/cats/tests/SemigroupKSuite.scala
new file mode 100644
index 0000000000..3c38cb27cb
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/SemigroupKSuite.scala
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Align, Alternative, SemigroupK}
+import cats.data.{Chain, Validated}
+import cats.laws.discipline.AlignTests
+import cats.laws.discipline.arbitrary._
+
+class SemigroupKSuite extends CatsSuite {
+ implicit val listwrapperSemigroupK: Alternative[ListWrapper] = ListWrapper.alternative
+ implicit val listwrapperAlign: Align[ListWrapper] = SemigroupK.align[ListWrapper]
+ checkAll("SemigroupK[ListWrapper].align", AlignTests[ListWrapper].align[Int, Int, Int, Int])
+
+ implicit val validatedAlign: Align[Validated[String, *]] = SemigroupK.align[Validated[String, *]]
+ checkAll("SemigroupK[Validated].align", AlignTests[Validated[String, *]].align[Int, Int, Int, Int])
+
+ implicit val chainAlign: Align[Chain] = SemigroupK.align[Chain]
+ checkAll("SemigroupK[Chain].align", AlignTests[Chain].align[Int, Int, Int, Int])
+}
diff --git a/tests/shared/src/test/scala/cats/tests/SemigroupSuite.scala b/tests/shared/src/test/scala/cats/tests/SemigroupSuite.scala
new file mode 100644
index 0000000000..18b29eb5b0
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/SemigroupSuite.scala
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Invariant, InvariantMonoidal, Semigroupal}
+import cats.kernel.Semigroup
+import cats.syntax.eq._
+import cats.kernel.laws.discipline.SemigroupTests
+import org.scalacheck.Prop._
+
+class SemigroupSuite extends CatsSuite {
+
+ {
+ Invariant[Semigroup]
+ Semigroupal[Semigroup]
+ InvariantMonoidal[Semigroup]
+ }
+
+ property("Semigroup.instance creates a Semigroup from the given function") {
+ val mult: (Int, Int) => Int = (a, b) => a * b
+ val add: (Int, Int) => Int = (a, b) => a + b
+
+ forAll { (a: Int, b: Int) =>
+ assert(Semigroup.instance(mult).combine(a, b) === (a * b))
+ assert(Semigroup.instance(add).combine(a, b) === (a + b))
+ }
+ }
+
+ {
+ val S = Semigroup.first[Int]
+ checkAll("Semigroup.first", SemigroupTests[Int](S).semigroup)
+ }
+
+ {
+ val S = Semigroup.last[Int]
+ checkAll("Semigroup.last", SemigroupTests[Int](S).semigroup)
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/SeqSuite.scala b/tests/shared/src/test/scala/cats/tests/SeqSuite.scala
similarity index 61%
rename from tests/src/test/scala/cats/tests/SeqSuite.scala
rename to tests/shared/src/test/scala/cats/tests/SeqSuite.scala
index 19374872d1..0d302fed15 100644
--- a/tests/src/test/scala/cats/tests/SeqSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/SeqSuite.scala
@@ -1,7 +1,28 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Align, Alternative, CoflatMap, Monad, Semigroupal, Traverse, TraverseFilter}
-import cats.data.{NonEmptySeq, ZipSeq}
+import cats.{Align, Alternative, CoflatMap, Eval, Monad, Semigroupal, Traverse, TraverseFilter}
+import cats.data.ZipSeq
import cats.laws.discipline.{
AlignTests,
AlternativeTests,
@@ -16,7 +37,6 @@ import cats.laws.discipline.{
}
import cats.laws.discipline.arbitrary._
import cats.syntax.show._
-import cats.syntax.seq._
import cats.syntax.eq._
import org.scalacheck.Prop._
import scala.collection.immutable.Seq
@@ -31,7 +51,9 @@ class SeqSuite extends CatsSuite {
checkAll("Seq[Int]", AlternativeTests[Seq].alternative[Int, Int, Int])
checkAll("Alternative[Seq]", SerializableTests.serializable(Alternative[Seq]))
+ // Traverse behaviour discriminates on the Runtime type of the Applicative
checkAll("Seq[Int] with Option", TraverseTests[Seq].traverse[Int, Int, Int, Set[Int], Option, Option])
+ checkAll("Seq[Int] with Eval", TraverseTests[Seq].traverse[Int, Int, Int, Set[Int], Eval, Eval])
checkAll("Traverse[Seq]", SerializableTests.serializable(Traverse[Seq]))
checkAll("Seq[Int]", MonadTests[Seq].monad[Int, Int, Int])
@@ -54,16 +76,6 @@ class SeqSuite extends CatsSuite {
}
}
- test("neSeq => Seq => neSeq returns original neSeq")(
- forAll { (fa: NonEmptySeq[Int]) =>
- assert(fa.toSeq.toNeSeq == Some(fa))
- }
- )
-
- test("toNeSeq on empty Seq returns None") {
- assert(Seq.empty[Int].toNeSeq == None)
- }
-
test("traverse is stack-safe") {
val seq = (0 until 100000).toSeq
val sumAll = Traverse[Seq]
diff --git a/tests/src/test/scala/cats/tests/SetSuite.scala b/tests/shared/src/test/scala/cats/tests/SetSuite.scala
similarity index 52%
rename from tests/src/test/scala/cats/tests/SetSuite.scala
rename to tests/shared/src/test/scala/cats/tests/SetSuite.scala
index ec4aba1264..ae1d6fed9e 100644
--- a/tests/src/test/scala/cats/tests/SetSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/SetSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{MonoidK, Show, UnorderedTraverse}
@@ -24,7 +45,7 @@ class SetSuite extends CatsSuite {
test("show keeps separate entries for items that map to identical strings") {
// note: this val name has to be the same to shadow the cats.instances instance
- implicit val catsStdShowForInt: Show[Int] = Show.show(_ => "1")
+ implicit val catsStdShowForInt: Show[Int] = _ => "1"
// an implementation implemented as set.map(_.show).mkString(", ") would
// only show one entry in the result instead of 3, because Set.map combines
// duplicate items in the codomain.
diff --git a/tests/shared/src/test/scala/cats/tests/ShowSuite.scala b/tests/shared/src/test/scala/cats/tests/ShowSuite.scala
new file mode 100644
index 0000000000..94f22c7bc0
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/ShowSuite.scala
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Contravariant, Show}
+import cats.Show.ContravariantShow
+import cats.kernel.Order
+import cats.syntax.show.*
+import cats.laws.discipline.{ContravariantTests, DeferTests, MiniInt, SerializableTests}
+import cats.laws.discipline.arbitrary.*
+import cats.laws.discipline.eq.*
+import java.util.concurrent.TimeUnit
+import scala.collection.immutable.BitSet
+import scala.collection.immutable.Seq
+import scala.collection.immutable.SortedMap
+import scala.collection.immutable.SortedSet
+import scala.concurrent.duration.{Duration, FiniteDuration}
+
+class ShowSuite extends CatsSuite {
+ checkAll("Contravariant[Show]", ContravariantTests[Show].contravariant[MiniInt, Int, Boolean])
+ checkAll("Contravariant[Show]", SerializableTests.serializable(Contravariant[Show]))
+ checkAll("Defer[Show]", DeferTests[Show].defer[MiniInt])
+
+ sealed trait TimeOfDay
+ case object Morning extends TimeOfDay
+ object TimeOfDay {
+ implicit val showTimeOfDay: Show[TimeOfDay] = { case Morning => "morning" }
+ }
+
+ test("show string interpolator") {
+ case class Cat(name: String)
+ object Cat {
+ implicit val showCat: Show[Cat] = _.name
+ }
+ val tod: TimeOfDay = Morning
+ val cat = Cat("Whiskers")
+
+ assertEquals("Good morning, Whiskers!", show"Good $tod, $cat!")
+
+ assertEquals("Good morning, Whiskers!", show"Good $tod, ${List(cat).head}!")
+ }
+
+ test("show string interpolator and contravariance") {
+ val tod: Morning.type = Morning
+
+ assertEquals("Good morning", show"Good $tod")
+ }
+
+ test("contravariant show is not ambiguous when both FiniteDuration's and Duration's instances are in scope") {
+ implicitly[ContravariantShow[FiniteDuration]]
+ implicitly[ContravariantShow[Duration]]
+ }
+
+ test("show interpolation works when both FiniteDuration's and Duration's instances are in scope") {
+ show"instance resolution is not ambiguous for ${FiniteDuration(3L, TimeUnit.SECONDS)}"
+ show"instance resolution is not ambiguous for ${Duration(3L, TimeUnit.SECONDS)}"
+ }
+
+ test("show interpolation with Seq subtypes isn't ambiguous") {
+ implicitly[ContravariantShow[Seq[Int]]]
+ implicitly[ContravariantShow[List[Int]]]
+ implicitly[ContravariantShow[Vector[Int]]]
+
+ val goodmornings = Seq("guten Tag", "good morning", "bonjour")
+ assertEquals(show"$goodmornings", "List(guten Tag, good morning, bonjour)")
+ assertEquals(show"${goodmornings.toList}", "List(guten Tag, good morning, bonjour)")
+ assertEquals(show"${goodmornings.toVector}", "Vector(guten Tag, good morning, bonjour)")
+ }
+
+ test("show interpolation with Set subtypes isn't ambiguous") {
+ implicitly[ContravariantShow[Set[Int]]]
+ implicitly[ContravariantShow[SortedSet[Int]]]
+ implicitly[ContravariantShow[BitSet]]
+
+ val numbers: Set[Int] = Set(4, 2, 1, 3)
+ // relies on the implementation of Set for <= 4 elements, maybe replace the rhs with numbers.mkString(...)?
+ assertEquals(show"$numbers", "Set(4, 2, 1, 3)")
+
+ val numbersSorted: SortedSet[Int] = SortedSet(4, 2, 1, 3)
+ assertEquals(show"$numbersSorted", "SortedSet(1, 2, 3, 4)")
+
+ val numbersBitSet: BitSet = BitSet(4, 2, 1, 3)
+ assertEquals(show"$numbersBitSet", "BitSet(1, 2, 3, 4)")
+ }
+
+ test("show interpolation with Map subtypes isn't ambiguous") {
+ implicitly[ContravariantShow[Map[Int, String]]]
+ implicitly[ContravariantShow[SortedMap[Int, String]]]
+
+ val map: Map[Int, String] = Map(3 -> "three", 1 -> "one", 4 -> "four", 2 -> "two")
+ // same thing as with Set, relies on an implementation detail of Map
+ assertEquals(show"$map", "Map(3 -> three, 1 -> one, 4 -> four, 2 -> two)")
+
+ val mapSorted: SortedMap[Int, String] = SortedMap(3 -> "three", 1 -> "one", 4 -> "four", 2 -> "two")
+ assertEquals(show"$mapSorted", "SortedMap(1 -> one, 2 -> two, 3 -> three, 4 -> four)")
+ }
+}
+
+final class ShowSuite2 extends munit.FunSuite {
+
+ test(
+ "contravariant show for FiniteDuration can be inferred when importing both duration's and finiteDuration's instances"
+ ) {
+
+ implicitly[Order[Duration]]
+ implicitly[Order[FiniteDuration]]
+
+ implicitly[ContravariantShow[FiniteDuration]]
+ }
+
+ test("all the Duration's and FiniteDuration's instances can be correctly inferred when importing implicits") {
+
+ implicitly[Order[Duration]]
+ implicitly[Order[FiniteDuration]]
+
+ implicitly[ContravariantShow[Duration]]
+ implicitly[ContravariantShow[FiniteDuration]]
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/SortedMapSuite.scala b/tests/shared/src/test/scala/cats/tests/SortedMapSuite.scala
similarity index 75%
rename from tests/src/test/scala/cats/tests/SortedMapSuite.scala
rename to tests/shared/src/test/scala/cats/tests/SortedMapSuite.scala
index 7c1a6f1626..39e3e0ebb4 100644
--- a/tests/src/test/scala/cats/tests/SortedMapSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/SortedMapSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{Align, FlatMap, MonoidK, Semigroupal, Show, Traverse, TraverseFilter}
diff --git a/tests/src/test/scala/cats/tests/SortedSetSuite.scala b/tests/shared/src/test/scala/cats/tests/SortedSetSuite.scala
similarity index 76%
rename from tests/src/test/scala/cats/tests/SortedSetSuite.scala
rename to tests/shared/src/test/scala/cats/tests/SortedSetSuite.scala
index 9d26fa923f..18be0acf48 100644
--- a/tests/src/test/scala/cats/tests/SortedSetSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/SortedSetSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{SemigroupK, Semigroupal, Show}
@@ -49,7 +70,7 @@ class SortedSetSuite extends CatsSuite {
test("show keeps separate entries for items that map to identical strings") {
// note: this val name has to be the same to shadow the cats.instances instance
- implicit val catsStdShowForInt: Show[Int] = Show.show(_ => "1")
+ implicit val catsStdShowForInt: Show[Int] = _ => "1"
// an implementation implemented as set.map(_.show).mkString(", ") would
// only show one entry in the result instead of 3, because SortedSet.map combines
// duplicate items in the codomain.
diff --git a/tests/shared/src/test/scala/cats/tests/SplitSuite.scala b/tests/shared/src/test/scala/cats/tests/SplitSuite.scala
new file mode 100644
index 0000000000..3be38e0e51
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/SplitSuite.scala
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.syntax.arrow._
+
+class SplitSuite extends CatsSuite {
+ test("syntax") {
+ val f = ((_: Int) + 1).split((_: Int) / 2)
+ assertEquals(f((1, 2)), (2, 1))
+ }
+}
diff --git a/tests/shared/src/test/scala/cats/tests/Spooky.scala b/tests/shared/src/test/scala/cats/tests/Spooky.scala
new file mode 100644
index 0000000000..1c9ed6ace9
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/Spooky.scala
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+/**
+ * Class for spooky side-effects and action-at-a-distance.
+ *
+ * It is basically a mutable counter that can be used to measure how
+ * many times an otherwise pure function is being evaluated.
+ */
+class Spooky(var counter: Int = 0) {
+ def increment(): Unit = counter += 1
+}
diff --git a/tests/src/test/scala/cats/tests/StreamSuite.scala b/tests/shared/src/test/scala/cats/tests/StreamSuite.scala
similarity index 63%
rename from tests/src/test/scala/cats/tests/StreamSuite.scala
rename to tests/shared/src/test/scala/cats/tests/StreamSuite.scala
index 65d95d0c2a..9ddb4557f9 100644
--- a/tests/src/test/scala/cats/tests/StreamSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/StreamSuite.scala
@@ -1,24 +1,34 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Align, Alternative, CoflatMap, Monad, Semigroupal, Traverse, TraverseFilter}
+import cats._
import cats.data.ZipStream
-import cats.laws.discipline.{
- AlignTests,
- AlternativeTests,
- CoflatMapTests,
- CommutativeApplyTests,
- MonadTests,
- SemigroupalTests,
- SerializableTests,
- ShortCircuitingTests,
- TraverseFilterTests,
- TraverseTests
-}
+import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
-import cats.syntax.show._
-import cats.syntax.eq._
+import cats.syntax.all._
import org.scalacheck.Prop._
+@annotation.nowarn("cat=deprecation")
class StreamSuite extends CatsSuite {
checkAll("Stream[Int]", SemigroupalTests[Stream].semigroupal[Int, Int, Int])
checkAll("Semigroupal[Stream]", SerializableTests.serializable(Semigroupal[Stream]))
@@ -69,14 +79,9 @@ class StreamSuite extends CatsSuite {
}
}
-}
-
-final class StreamInstancesSuite extends munit.FunSuite {
-
- test("parallel instance in cats.instances.stream") {
- import cats.instances.stream._
- import cats.syntax.parallel._
-
- (Stream(1, 2, 3), Stream("A", "B", "C")).parTupled
+ test("NonEmptyParallel instance in cats.instances.stream") {
+ forAll { (s1: Stream[Int], s2: Stream[String]) =>
+ assert((s1, s2).parTupled === s1.zip(s2))
+ }
}
}
diff --git a/tests/shared/src/test/scala/cats/tests/SyntaxSerializationSuite.scala b/tests/shared/src/test/scala/cats/tests/SyntaxSerializationSuite.scala
new file mode 100644
index 0000000000..5ea5b3e4d7
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/SyntaxSerializationSuite.scala
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.laws.discipline.SerializableTests
+import cats.syntax.either._
+import cats.Semigroupal
+
+/**
+ * Test that our syntax implicits are serializable.
+ */
+class SyntaxSerializationSuite extends CatsSuite {
+ checkAll(
+ "Tuple3SemigroupalOps[Option, Boolean, Int, Long]",
+ SerializableTests.serializable(
+ cats.syntax.all.catsSyntaxTuple3Semigroupal[Option, Boolean, Int, Long]((None, None, None))
+ )
+ )
+
+ checkAll("SemigroupalOps[Option, Int]",
+ SerializableTests.serializable(cats.syntax.all.catsSyntaxSemigroupal[Option, Int](None, Semigroupal[Option]))
+ )
+
+ checkAll(
+ "Tuple3ParallelOps[Either[String, *], Boolean, Int, Long]",
+ SerializableTests.serializable(
+ cats.syntax.all.catsSyntaxTuple3Parallel(("a".asLeft[Boolean], "b".asLeft[Int], "c".asLeft[Long]))
+ )
+ )
+}
diff --git a/tests/src/test/scala/cats/tests/SyntaxSuite.scala b/tests/shared/src/test/scala/cats/tests/SyntaxSuite.scala
similarity index 65%
rename from tests/src/test/scala/cats/tests/SyntaxSuite.scala
rename to tests/shared/src/test/scala/cats/tests/SyntaxSuite.scala
index 52a98b2620..2b7f19277d 100644
--- a/tests/src/test/scala/cats/tests/SyntaxSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/SyntaxSuite.scala
@@ -1,9 +1,46 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
import cats.arrow.Compose
-import cats.data.{Binested, Nested, NonEmptyChain, NonEmptyList, NonEmptySet}
+import cats.data.{
+ Binested,
+ EitherNec,
+ EitherNel,
+ EitherNes,
+ EitherT,
+ Ior,
+ Nested,
+ NonEmptyChain,
+ NonEmptyList,
+ NonEmptySet,
+ OptionT,
+ Validated,
+ ValidatedNec,
+ ValidatedNel
+}
import cats.syntax.all._
+
import scala.collection.immutable.{SortedMap, SortedSet}
/**
@@ -117,11 +154,11 @@ object SyntaxSuite {
val a1: A = fz.foldMap(f3)
val f4 = mock[A => G[B]]
- val gu0: G[Unit] = fa.traverse_(f4)
+ val gu0: G[Unit] = fa.traverseVoid(f4)
val fga = mock[F[G[A]]]
- val gu1: G[Unit] = fga.sequence_
- val ga: G[A] = fga.foldK
+ val gu1: G[Unit] = fga.sequenceVoid // NestedFoldableOps
+ val ga1: G[A] = fga.foldK // NestedFoldableOps
val f5 = mock[A => Boolean]
val oa: Option[A] = fa.find(f5)
@@ -163,7 +200,19 @@ object SyntaxSuite {
val gunit: G[F[A]] = fga.nonEmptySequence
}
- def testParallel[M[_]: Monad, F[_], T[_]: Traverse, A, B](implicit P: Parallel.Aux[M, F]): Unit = {
+ def testParallelFoldable[M[_]: Parallel, T[_]: Foldable, A, B](): Unit = {
+ val ta = mock[T[A]]
+ val tma = mock[T[M[A]]]
+ val famb = mock[A => M[B]]
+
+ val mu1 = ta.parTraverseVoid(famb)
+ val mu2 = tma.parSequenceVoid
+
+ // Suppress "unused local val" warnings and make sure the types were inferred correctly.
+ val _ = (mu1: M[Unit], mu2: M[Unit])
+ }
+
+ def testParallelTraverse[M[_]: Parallel, T[_]: Traverse, A, B](): Unit = {
val ta = mock[T[A]]
val f = mock[A => M[B]]
val mtb = ta.parTraverse(f)
@@ -171,6 +220,13 @@ object SyntaxSuite {
val tma = mock[T[M[A]]]
val mta = tma.parSequence
+ val ma = mock[M[A]]
+
+ val mla: M[List[A]] = ma.parReplicateA(mock[Int])
+ val mu: M[Unit] = ma.parReplicateA_(mock[Int])
+ }
+
+ def testNonEmptyParallel[M[_]: NonEmptyParallel, A, B]: Unit = {
val ma = mock[M[A]]
val mb = mock[M[B]]
@@ -184,7 +240,6 @@ object SyntaxSuite {
val mb4: M[B] = ma.parProductR(mb)
val mab2: M[(A, B)] = ma.parProduct(mb)
val mb5: M[B] = mab.parAp(ma)
- val mla: M[List[A]] = ma.parReplicateA(mock[Int])
}
def testParallelUnorderedTraverse[M[_]: Monad, F[_]: CommutativeApplicative, T[_]: UnorderedTraverse: FlatMap, A, B](
@@ -214,14 +269,80 @@ object SyntaxSuite {
}
def testParallelTuple[M[_]: Monad, F[_], A, B, C, Z](implicit P: NonEmptyParallel.Aux[M, F]) = {
- val tfabc = mock[(M[A], M[B], M[C])]
val fa = mock[M[A]]
val fb = mock[M[B]]
val fc = mock[M[C]]
- val f = mock[(A, B, C) => Z]
- tfabc.parMapN(f)
- (fa, fb, fc).parMapN(f)
+ val tfabc = mock[(M[A], M[B], M[C])]
+ val fthree = mock[(A, B, C) => Z]
+ val mfthree = mock[(A, B, C) => M[Z]]
+
+ tfabc.parMapN(fthree)
+ (fa, fb, fc).parMapN(fthree)
+ tfabc.parFlatMapN(mfthree)
+ (fa, fb, fc).parFlatMapN(mfthree)
+
+ val tfab = mock[(M[A], M[B])]
+ val ftwo = mock[(A, B) => Z]
+ val mftwo = mock[(A, B) => M[Z]]
+
+ tfab.parMapN(ftwo)
+ (fa, fb).parMapN(ftwo)
+ tfab.parFlatMapN(mftwo)
+ (fa, fb).parFlatMapN(mftwo)
+
+ val tfa = mock[Tuple1[M[A]]]
+ val mfone = mock[A => M[Z]]
+
+ tfa.parFlatMap(mfone)
+ }
+
+ def testLiftN[F[_]: Apply, A, B, C, T] = {
+ val fa = mock[F[A]]
+ val fb = mock[F[B]]
+ val fc = mock[F[C]]
+
+ val fapply1 = mock[A => T]
+
+ val result1 = fapply1.liftN(fa)
+
+ result1: F[T]
+
+ val fapply2 = mock[(A, B) => T]
+
+ val result2 = fapply2.liftN(fa, fb)
+
+ result2: F[T]
+
+ val fapply3 = mock[(A, B, C) => T]
+
+ val result3 = fapply3.liftN(fa, fb, fc)
+
+ result3: F[T]
+ }
+
+ def testParLiftN[F[_]: Parallel: Functor, A, B, C, T] = {
+ val fa = mock[F[A]]
+ val fb = mock[F[B]]
+ val fc = mock[F[C]]
+
+ val fapply1 = mock[A => T]
+
+ val result1 = fapply1.parLiftN(fa)
+
+ result1: F[T]
+
+ val fapply2 = mock[(A, B) => T]
+
+ val result2 = fapply2.parLiftN(fa, fb)
+
+ result2: F[T]
+
+ val fapply3 = mock[(A, B, C) => T]
+
+ val result3 = fapply3.parLiftN(fa, fb, fc)
+
+ result3: F[T]
}
def testParallelBi[M[_], F[_], T[_, _]: Bitraverse, A, B, C, D](implicit P: Parallel.Aux[M, F]): Unit = {
@@ -238,7 +359,7 @@ object SyntaxSuite {
val mtab2 = tmab.parLeftSequence
}
- def testParallelFoldable[T[_]: Foldable, M[_]: Parallel, A, B: Monoid]: Unit = {
+ def testParallelFoldableMonoid[T[_]: Foldable, M[_]: Parallel, A, B: Monoid](): Unit = {
val ta = mock[T[A]]
val f = mock[A => M[B]]
val mb = ta.parFoldMapA(f)
@@ -269,9 +390,9 @@ object SyntaxSuite {
val lb: Eval[B] = fa.reduceRightTo(f4)(f6)
val f7 = mock[A => G[B]]
- val gu1: G[Unit] = fa.nonEmptyTraverse_(f7)
+ val gu1: G[Unit] = fa.nonEmptyTraverseVoid(f7)
- val gu2: G[Unit] = fga.nonEmptySequence_
+ val gu2: G[Unit] = fga.nonEmptySequenceVoid
}
def testFunctor[F[_]: Functor, A, B]: Unit = {
@@ -284,6 +405,9 @@ object SyntaxSuite {
val b = mock[B]
val fb1: F[B] = fa.as(b)
+
+ val c = mock[F[Boolean]]
+ c.ifF(1, 0)
}
def testApply[F[_]: Apply: Semigroupal,
@@ -303,6 +427,8 @@ object SyntaxSuite {
val f = mock[(A, B, C) => Z]
val ff = mock[F[(A, B, C) => Z]]
+ fa.productR(fb)
+ fa.productL(fb)
fa *> fb
fb <* fc
@@ -329,6 +455,19 @@ object SyntaxSuite {
thabcde.imapN(f5)(g5)
(ha, hb, hc, hd, he).imapN(f5)(g5)
+
+ val tfab = mock[F[A => B]]
+ tfab.ap(fa)
+ tfab <*> fa
+
+ val tabcf = mock[F[(A, B) => C]]
+ tabcf.ap2(fa, fb)
+
+ val tabc = mock[(A, B) => C]
+ fa.map2(fb)(tabc)
+
+ val tEvalfb = mock[Eval[F[B]]]
+ fa.map2Eval(tEvalfb)(tabc)
}
def testBifoldable[F[_, _]: Bifoldable, A, B, C, D: Monoid]: Unit = {
@@ -386,12 +525,23 @@ object SyntaxSuite {
def testApplicative[F[_]: Applicative, A]: Unit = {
val a = mock[A]
val fa = a.pure[F]
+ val replicateA = fa.replicateA(1)
+ val replicateA_ = fa.replicateA_(1)
}
- def testFlatMap[F[_]: FlatMap, A, B, C, D]: Unit = {
+ def testFlatMap[F[_]: FlatMap, A, B, C, D, Z]: Unit = {
val a = mock[A]
val returnValue = mock[F[Either[A, B]]]
val done = a.tailRecM[F, B](a => returnValue)
+ val tfabc = mock[(F[A], F[B], F[C])]
+ val ff = mock[(A, B, C) => F[Z]]
+
+ tfabc.flatMapN(ff)
+
+ val tfa = mock[Tuple1[F[A]]]
+ val ffone = mock[A => F[Z]]
+
+ tfa.flatMap(ffone)
val x = mock[Function[A, F[B]]]
val y = mock[Function[B, F[C]]]
@@ -415,6 +565,9 @@ object SyntaxSuite {
val ea = mock[E => A]
val gea1 = ga.handleError(ea)
+ val geu = mock[G[Unit]]
+ val veu = geu.voidError
+
val egea = mock[E => G[A]]
val gea2 = ga.handleErrorWith(egea)
@@ -482,6 +635,69 @@ object SyntaxSuite {
val nested: Nested[F, G, A] = fga.nested
}
+ def testEither[F[_]: Applicative, A: Order, B: Order](): Unit = {
+ val either = mock[Either[A, B]]
+ val a = mock[A]
+ val b = mock[B]
+
+ val v1: Validated[A, B] = either.toValidated
+ val v2: ValidatedNel[A, B] = either.toValidatedNel
+ val v3: Validated[F[A], B] = either.toValidated.leftLiftTo[F]
+
+ val v4: Either[F[A], B] = either.leftLiftTo[F]
+ val v5: EitherT[F, A, B] = either.toEitherT
+ val v6: EitherNel[A, B] = either.toEitherNel
+ val v7: EitherNec[A, B] = either.toEitherNec
+ val v8: EitherNes[A, B] = either.toEitherNes
+
+ val v9: Either[A, B] = Either.left[A, B](a)
+ val v10: Either[A, B] = Either.right[A, B](b)
+
+ val v11: EitherNec[A, Nothing] = Either.leftNec(a)
+ val v12: EitherNec[Nothing, B] = Either.rightNec(b)
+ val v13: EitherNes[A, Nothing] = Either.leftNes(a)
+ val v14: EitherNes[Nothing, B] = Either.rightNes(b)
+ val v15: EitherNel[A, Nothing] = Either.leftNel(a)
+ val v16: EitherNel[Nothing, B] = Either.rightNel(b)
+ }
+
+ def testOption[F[_]: Applicative, G[_], A, B: Monoid](): Unit = {
+ val option = mock[Option[B]]
+ val a = mock[A]
+ val b = mock[B]
+ implicit val aega: ApplicativeError[G, B] = mock[ApplicativeError[G, B]]
+
+ val v1: Validated[B, A] = option.toInvalid(a)
+ val v2: ValidatedNel[B, A] = option.toInvalidNel(a)
+ val v3: Validated[F[B], A] = option.toInvalid(a).leftLiftTo[F]
+ val v4: ValidatedNec[B, A] = option.toInvalidNec(a)
+ val v5: Validated[B, B] = option.toValid(b)
+ val v6: ValidatedNel[B, B] = option.toValidNel(b)
+ val v7: ValidatedNec[B, B] = option.toValidNec(b)
+ val v8: Ior[B, B] = option.toRightIor(b)
+ val v9: Ior[B, A] = option.toLeftIor(a)
+ val v10: EitherNel[B, B] = option.toRightNel(b)
+ val v11: EitherNec[B, B] = option.toRightNec(b)
+ val v12: EitherNel[B, A] = option.toLeftNel(a)
+ val v13: EitherNec[B, A] = option.toLeftNec(a)
+ val v14: B = option.orEmpty
+ val v15 = option.liftTo[F]
+ val v16: G[Unit] = option.raiseTo[G]
+ val v17: OptionT[F, B] = option.toOptionT[F]
+ }
+
+ def testValidated[F[_]: Applicative, A: Order, B: Order: Monoid](): Unit = {
+ val validated = mock[Validated[A, B]]
+ val a = mock[A]
+ val b = mock[B]
+
+ val v1: Validated[A, B] = b.valid[A]
+ val v2: Validated[F[A], A] = a.invalid[A].leftLiftTo[F]
+ val v3: ValidatedNel[A, B] = b.validNel[A]
+ val v4: Validated[A, B] = a.invalid[B]
+ val v5: ValidatedNel[A, B] = a.invalidNel[B]
+ }
+
def testBinested[F[_, _], G[_], H[_], A, B]: Unit = {
val fgahb = mock[F[G[A], H[B]]]
@@ -539,4 +755,19 @@ object SyntaxSuite {
val result: Either[A, List[B]] = f.sequenceFilter
}
+
+ def testTraverseCollect[A, B]: Unit = {
+ val list = mock[List[A]]
+ val f = mock[PartialFunction[A, Option[B]]]
+
+ val result: Option[List[B]] = list.traverseCollect(f)
+ }
+
+ def testSemigroupal[F[_]: Semigroupal, A, B]: Unit = {
+ val fa = mock[F[A]]
+ val fb = mock[F[B]]
+
+ fa.product(fb)
+ fa |@| fb
+ }
}
diff --git a/tests/shared/src/test/scala/cats/tests/TailRecSuite.scala b/tests/shared/src/test/scala/cats/tests/TailRecSuite.scala
new file mode 100644
index 0000000000..e460ae4ad0
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/TailRecSuite.scala
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.{Defer, Monad}
+import cats.kernel.Eq
+import cats.laws.discipline.{DeferTests, MonadTests, SerializableTests}
+import scala.util.control.TailCalls.{done, tailcall, TailRec}
+import org.scalacheck.{Arbitrary, Cogen, Gen}
+import org.scalacheck.Arbitrary.arbitrary
+
+class TailRecSuite extends CatsSuite {
+
+ implicit def tailRecArb[A: Arbitrary: Cogen]: Arbitrary[TailRec[A]] =
+ Arbitrary(
+ Gen.frequency(
+ (3, arbitrary[A].map(done(_))),
+ (1, Gen.lzy(arbitrary[(A, A => TailRec[A])].map { case (a, fn) => tailcall(fn(a)) })),
+ (1, Gen.lzy(arbitrary[(TailRec[A], A => TailRec[A])].map { case (a, fn) => a.flatMap(fn) }))
+ )
+ )
+
+ implicit def eqTailRec[A: Eq]: Eq[TailRec[A]] =
+ Eq.by[TailRec[A], A](_.result)
+
+ checkAll("TailRec[Int]", MonadTests[TailRec].monad[Int, Int, Int])
+ checkAll("Monad[TailRec]", SerializableTests.serializable(Monad[TailRec]))
+
+ checkAll("TailRec[Int]", DeferTests[TailRec].defer[Int])
+ checkAll("Defer[TailRec]", SerializableTests.serializable(Defer[TailRec]))
+}
diff --git a/tests/shared/src/test/scala/cats/tests/TraverseFilterSuite.scala b/tests/shared/src/test/scala/cats/tests/TraverseFilterSuite.scala
new file mode 100644
index 0000000000..92d8131d6d
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/TraverseFilterSuite.scala
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Traverse
+import cats.TraverseFilter
+import cats.data.Chain
+import cats.laws.discipline.arbitrary.catsLawsArbitraryForChain
+import cats.syntax.all._
+import org.scalacheck.Arbitrary
+import org.scalacheck.Prop.forAll
+
+import scala.collection.immutable.Queue
+
+abstract class TraverseFilterSuite[F[_]: TraverseFilter](name: String)(implicit
+ ArbFInt: Arbitrary[F[Int]],
+ ArbFString: Arbitrary[F[String]]
+) extends CatsSuite {
+
+ implicit def T: Traverse[F] = implicitly[TraverseFilter[F]].traverse
+
+ test(s"TraverseFilter[$name].ordDistinct") {
+ forAll { (fa: F[Int]) =>
+ fa.ordDistinct.toList === fa.toList.distinct
+ }
+ }
+
+ test(s"TraverseFilter[$name].hashDistinct") {
+ forAll { (fa: F[String]) =>
+ fa.hashDistinct.toList === fa.toList.distinct
+ }
+ }
+}
+
+class TraverseFilterListSuite extends TraverseFilterSuite[List]("list")
+
+class TraverseFilterVectorSuite extends TraverseFilterSuite[Vector]("vector")
+
+class TraverseFilterChainSuite extends TraverseFilterSuite[Chain]("chain")
+
+class TraverseFilterQueueSuite extends TraverseFilterSuite[Queue]("queue")
+
+@annotation.nowarn("cat=deprecation")
+class TraverseFilterStreamSuite extends TraverseFilterSuite[Stream]("stream")
diff --git a/tests/shared/src/test/scala/cats/tests/TraverseSuite.scala b/tests/shared/src/test/scala/cats/tests/TraverseSuite.scala
new file mode 100644
index 0000000000..6d64bfa794
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/TraverseSuite.scala
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats._
+import cats.data.Chain
+import cats.kernel.compat.scalaVersionSpecific._
+import cats.laws.discipline.arbitrary._
+import cats.syntax.all._
+import org.scalacheck.Arbitrary
+import org.scalacheck.Prop._
+
+@suppressUnusedImportWarningForScalaVersionSpecific
+abstract class TraverseSuite[F[_]: Traverse](name: String)(implicit ArbFInt: Arbitrary[F[Int]]) extends CatsSuite {
+
+ test(s"Traverse[$name].zipWithIndex") {
+ forAll { (fa: F[Int]) =>
+ assert(fa.zipWithIndex.toList === (fa.toList.zipWithIndex))
+ }
+ }
+
+ test(s"Traverse[$name].zipWithLongIndex") {
+ forAll { (fa: F[Int]) =>
+ assert(fa.zipWithLongIndex.toList === (fa.toList.zipWithLongIndex))
+ }
+ }
+
+ test(s"Traverse[$name].mapAccumulate") {
+ forAll { (init: Int, fa: F[Int], fn: ((Int, Int)) => (Int, Int)) =>
+ val lhs = fa.mapAccumulate(init)((s, a) => fn((s, a)))
+
+ val rhs = fa.foldLeft((init, List.empty[Int])) { case ((s1, acc), a) =>
+ val (s2, b) = fn((s1, a))
+ (s2, b :: acc)
+ }
+
+ assert(lhs.map(_.toList) === rhs.map(_.reverse))
+ }
+ }
+
+ test(s"Traverse[$name].mapWithIndex") {
+ forAll { (fa: F[Int], fn: ((Int, Int)) => Int) =>
+ assert(fa.mapWithIndex((a, i) => fn((a, i))).toList === (fa.toList.zipWithIndex.map(fn)))
+ }
+ }
+
+ test(s"Traverse[$name].mapWithLongIndex") {
+ forAll { (fa: F[Int], fn: ((Int, Long)) => Int) =>
+ assert(fa.mapWithLongIndex((a, i) => fn((a, i))).toList === (fa.toList.zipWithLongIndex.map(fn)))
+ }
+ }
+
+ test(s"Traverse[$name].traverseWithIndexM") {
+ forAll { (fa: F[Int], fn: ((Int, Int)) => (Int, Int)) =>
+ val left = fa.traverseWithIndexM((a, i) => fn((a, i))).fmap(_.toList)
+ val (xs, values) = fa.toList.zipWithIndex.map(fn).unzip
+ assert(left === ((xs.combineAll, values)))
+ }
+ }
+
+ test(s"Traverse[$name].traverseWithLongIndexM") {
+ forAll { (fa: F[Int], fn: ((Int, Long)) => (Int, Long)) =>
+ val left = fa.traverseWithLongIndexM((a, i) => fn((a, i))).fmap(_.toList)
+ val (xs, values) = fa.toList.zipWithLongIndex.map(fn).unzip
+ assert(left === ((xs.combineAll, values)))
+ }
+ }
+
+ test(s"Traverse[$name].traverse matches traverseVoid with Option") {
+ forAll { (fa: F[Int], fn: Int => Option[Int]) =>
+ assert(Applicative[Option].void(fa.traverse(fn)) == fa.traverseVoid(fn))
+ }
+ }
+
+ test(s"Traverse[$name].updated_") {
+ forAll { (fa: F[Int], i: Int, b: Int) =>
+ val updatedThenToList: Option[List[Int]] = fa.updated_(i.toLong, b).fmap(_.toList)
+ val toListThenUpdated: Option[List[Int]] = scala.util.Try(fa.toList.updated(i, b)).toOption
+ assertEquals(updatedThenToList, toListThenUpdated)
+ }
+ }
+
+}
+
+object TraverseSuite {
+ // forces testing of the underlying implementation (avoids overridden methods)
+ abstract class Underlying[F[_]: Traverse](name: String)(implicit ArbFInt: Arbitrary[F[Int]])
+ extends TraverseSuite(s"$name (underlying)")(proxyTraverse[F], ArbFInt)
+
+ // proxies a traverse instance so we can test default implementations
+ // to achieve coverage using default datatype instances
+ private def proxyTraverse[F[_]: Traverse]: Traverse[F] =
+ new Traverse[F] {
+ def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B =
+ Traverse[F].foldLeft(fa, b)(f)
+ def foldRight[A, B](fa: F[A], lb: cats.Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
+ Traverse[F].foldRight(fa, lb)(f)
+ def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] =
+ Traverse[F].traverse(fa)(f)
+ }
+}
+
+class TraverseListSuite extends TraverseSuite[List]("List")
+class TraverseVectorSuite extends TraverseSuite[Vector]("Vector")
+class TraverseChainSuite extends TraverseSuite[Chain]("Chain")
+
+@annotation.nowarn("cat=deprecation")
+class TraverseStreamSuite extends TraverseSuite[Stream]("Stream")
+
+class TraverseListSuiteUnderlying extends TraverseSuite.Underlying[List]("List")
+class TraverseVectorSuiteUnderlying extends TraverseSuite.Underlying[Vector]("Vector")
+
+@annotation.nowarn("cat=deprecation")
+class TraverseStreamSuiteUnderlying extends TraverseSuite.Underlying[Stream]("Stream")
+
+class TraverseSuiteAdditional
+ extends CatsSuite
+ with ScalaVersionSpecificTraverseSuite
+ with TraverseSuiteAdditionalStreamSpecific {
+
+ def checkZipWithIndexedStackSafety[F[_]](fromRange: Range => F[Int])(implicit F: Traverse[F]): Unit = {
+ F.zipWithIndex(fromRange(1 to 70000))
+ ()
+ }
+
+ test("Traverse[List].zipWithIndex stack safety") {
+ checkZipWithIndexedStackSafety[List](_.toList)
+ }
+
+ test("Traverse[Vector].zipWithIndex stack safety") {
+ checkZipWithIndexedStackSafety[Vector](_.toVector)
+ }
+}
+
+@annotation.nowarn("cat=deprecation")
+sealed trait TraverseSuiteAdditionalStreamSpecific { self: TraverseSuiteAdditional =>
+ test("Traverse[Stream].zipWithIndex stack safety") {
+ checkZipWithIndexedStackSafety[Stream](_.toStream)
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/TrySuite.scala b/tests/shared/src/test/scala/cats/tests/TrySuite.scala
similarity index 80%
rename from tests/src/test/scala/cats/tests/TrySuite.scala
rename to tests/shared/src/test/scala/cats/tests/TrySuite.scala
index a23b251bc3..8208cfad11 100644
--- a/tests/src/test/scala/cats/tests/TrySuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/TrySuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{CoflatMap, Eval, Later, Monad, MonadThrow, Semigroupal, Traverse}
diff --git a/tests/src/test/scala/cats/tests/Tuple2KSuite.scala b/tests/shared/src/test/scala/cats/tests/Tuple2KSuite.scala
similarity index 89%
rename from tests/src/test/scala/cats/tests/Tuple2KSuite.scala
rename to tests/shared/src/test/scala/cats/tests/Tuple2KSuite.scala
index 0ba855bf31..ac4f93a032 100644
--- a/tests/src/test/scala/cats/tests/Tuple2KSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/Tuple2KSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
diff --git a/tests/src/test/scala/cats/tests/TupleSuite.scala b/tests/shared/src/test/scala/cats/tests/TupleSuite.scala
similarity index 88%
rename from tests/src/test/scala/cats/tests/TupleSuite.scala
rename to tests/shared/src/test/scala/cats/tests/TupleSuite.scala
index fd44dfc50b..37b2981904 100644
--- a/tests/src/test/scala/cats/tests/TupleSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/TupleSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{
@@ -228,9 +249,9 @@ class TupleSuite extends CatsSuite {
assert((foo1, bar1).show === s"(${Show[Foo].show(foo1)},${Show[Bar].show(bar1)})")
assert((foo1, bar1, baz1).show === s"(${Show[Foo].show(foo1)},${Show[Bar].show(bar1)},${Show[Baz].show(baz1)})")
assert((foo1, bar1, baz1, foo2, bar2, baz2).show === s"(${Show[Foo].show(foo1)},${Show[Bar].show(bar1)},${Show[Baz]
- .show(baz1)},${Show[Foo].show(foo2)},${Show[Bar].show(bar2)},${Show[Baz].show(baz2)})")
+ .show(baz1)},${Show[Foo].show(foo2)},${Show[Bar].show(bar2)},${Show[Baz].show(baz2)})")
assert((foo1, bar1, baz1, foo2, bar2, baz2, foo3, bar3, baz3).show === s"(${Show[Foo].show(foo1)},${Show[Bar]
- .show(bar1)},${Show[Baz].show(baz1)},${Show[Foo].show(foo2)},${Show[Bar].show(bar2)},${Show[Baz]
- .show(baz2)},${Show[Foo].show(foo3)},${Show[Bar].show(bar3)},${Show[Baz].show(baz3)})")
+ .show(bar1)},${Show[Baz].show(baz1)},${Show[Foo].show(foo2)},${Show[Bar].show(bar2)},${Show[Baz]
+ .show(baz2)},${Show[Foo].show(foo3)},${Show[Bar].show(bar3)},${Show[Baz].show(baz3)})")
}
}
diff --git a/tests/src/test/scala/cats/tests/UnorderedFoldableSuite.scala b/tests/shared/src/test/scala/cats/tests/UnorderedFoldableSuite.scala
similarity index 68%
rename from tests/src/test/scala/cats/tests/UnorderedFoldableSuite.scala
rename to tests/shared/src/test/scala/cats/tests/UnorderedFoldableSuite.scala
index 86842f4770..cf9593e81a 100644
--- a/tests/src/test/scala/cats/tests/UnorderedFoldableSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/UnorderedFoldableSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.UnorderedFoldable
@@ -47,6 +68,14 @@ sealed abstract class UnorderedFoldableSuite[F[_]](name: String)(implicit
assert(fa.count(Function.const(true)) === (fa.size))
}
}
+
+ test(s"UnorderedFoldable[$name].contains") {
+ forAll { (fa: F[String], v: String) =>
+ implicit val F: UnorderedFoldable[F] = instance
+ assert(fa.contains_(v) === (iterator(fa).contains(v)))
+ }
+ }
+
checkAll("F[Int]", UnorderedFoldableTests[F](instance).unorderedFoldable[Int, Int])
}
diff --git a/tests/shared/src/test/scala/cats/tests/UnorderedTraverseSuite.scala b/tests/shared/src/test/scala/cats/tests/UnorderedTraverseSuite.scala
new file mode 100644
index 0000000000..301d3b52ae
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/UnorderedTraverseSuite.scala
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.Id
+import cats.syntax.unorderedTraverse._
+import cats.syntax.eq._
+import org.scalacheck.Prop._
+
+class UnorderedTraverseSuite extends CatsSuite {
+ test("UnorderedTraverse[Set[Int]].unorderedTraverse via syntax") {
+ forAll { (ins: Set[Int]) =>
+ assert(ins.unorderedTraverse(in => in: Id[Int]).toList.sorted === (ins.toList.sorted))
+ }
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/ValidatedSuite.scala b/tests/shared/src/test/scala/cats/tests/ValidatedSuite.scala
similarity index 91%
rename from tests/src/test/scala/cats/tests/ValidatedSuite.scala
rename to tests/shared/src/test/scala/cats/tests/ValidatedSuite.scala
index 281afc9c0a..4283b38c0c 100644
--- a/tests/src/test/scala/cats/tests/ValidatedSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/ValidatedSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.{
diff --git a/tests/src/test/scala/cats/tests/VarianceSuite.scala b/tests/shared/src/test/scala/cats/tests/VarianceSuite.scala
similarity index 70%
rename from tests/src/test/scala/cats/tests/VarianceSuite.scala
rename to tests/shared/src/test/scala/cats/tests/VarianceSuite.scala
index 690dc1d6e7..e06aec55b9 100644
--- a/tests/src/test/scala/cats/tests/VarianceSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/VarianceSuite.scala
@@ -1,8 +1,29 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.arrow.Profunctor
import cats.conversions.all._
-import cats.implicits._
+import cats.syntax.all._
import cats.{Bifunctor, Contravariant, Functor}
class VarianceSuite extends CatsSuite {
diff --git a/tests/src/test/scala/cats/tests/VectorSuite.scala b/tests/shared/src/test/scala/cats/tests/VectorSuite.scala
similarity index 72%
rename from tests/src/test/scala/cats/tests/VectorSuite.scala
rename to tests/shared/src/test/scala/cats/tests/VectorSuite.scala
index 8581022f65..4777dab5b1 100644
--- a/tests/src/test/scala/cats/tests/VectorSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/VectorSuite.scala
@@ -1,6 +1,27 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
-import cats.{Align, Alternative, CoflatMap, Monad, Semigroupal, Traverse, TraverseFilter}
+import cats.{Align, Alternative, CoflatMap, Eval, Monad, Semigroupal, Traverse, TraverseFilter}
import cats.data.{NonEmptyVector, ZipVector}
import cats.laws.discipline.{
AlignTests,
@@ -30,7 +51,9 @@ class VectorSuite extends CatsSuite {
checkAll("Vector[Int]", AlternativeTests[Vector].alternative[Int, Int, Int])
checkAll("Alternative[Vector]", SerializableTests.serializable(Alternative[Vector]))
+ // TraverseFilter behaviour discriminates on the Runtime type of the Applicative
checkAll("Vector[Int] with Option", TraverseTests[Vector].traverse[Int, Int, Int, Set[Int], Option, Option])
+ checkAll("Vector[Int] with Eval", TraverseTests[Vector].traverse[Int, Int, Int, Set[Int], Eval, Eval])
checkAll("Traverse[Vector]", SerializableTests.serializable(Traverse[Vector]))
checkAll("Vector[Int]", MonadTests[Vector].monad[Int, Int, Int])
diff --git a/tests/src/test/scala/cats/tests/WordCountSuite.scala b/tests/shared/src/test/scala/cats/tests/WordCountSuite.scala
similarity index 63%
rename from tests/src/test/scala/cats/tests/WordCountSuite.scala
rename to tests/shared/src/test/scala/cats/tests/WordCountSuite.scala
index a30a8400c1..049604dd54 100644
--- a/tests/src/test/scala/cats/tests/WordCountSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/WordCountSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats.data.{AppFunc, Const}
diff --git a/tests/shared/src/test/scala/cats/tests/WriterSuite.scala b/tests/shared/src/test/scala/cats/tests/WriterSuite.scala
new file mode 100644
index 0000000000..0fbb3ec426
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/WriterSuite.scala
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats.tests
+
+import cats.data.Writer
+import cats.syntax.applicative._
+import cats.syntax.writer._
+import cats.syntax.eq._
+import org.scalacheck.Prop._
+
+class WriterSuite extends CatsSuite {
+ test("pure syntax creates a writer with an empty log") {
+ forAll { (result: String) =>
+ type Logged[A] = Writer[List[Int], A]
+ assert(result.pure[Logged] === (Writer(List.empty[Int], result)))
+ }
+ }
+
+ test("tell syntax creates a writer with a unit result") {
+ forAll { (log: List[Int]) =>
+ assert(log.tell === (Writer(log, ())))
+ }
+ }
+
+ test("writer syntax creates a writer with the specified result and log") {
+ forAll { (result: String, log: List[Int]) =>
+ assert(result.writer(log) === (Writer(log, result)))
+ }
+ }
+
+ test("catsDataCommutativeMonadForWriterT and catsDataTraverseForWriterTId instances are not ambiguous") {
+ import cats.Functor
+ Functor[Writer[Int, *]]
+ }
+}
diff --git a/tests/src/test/scala/cats/tests/WriterTSuite.scala b/tests/shared/src/test/scala/cats/tests/WriterTSuite.scala
similarity index 95%
rename from tests/src/test/scala/cats/tests/WriterTSuite.scala
rename to tests/shared/src/test/scala/cats/tests/WriterTSuite.scala
index b207586bee..535d77c747 100644
--- a/tests/src/test/scala/cats/tests/WriterTSuite.scala
+++ b/tests/shared/src/test/scala/cats/tests/WriterTSuite.scala
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
package cats.tests
import cats._
diff --git a/tests/shared/src/test/scala/cats/tests/package.scala b/tests/shared/src/test/scala/cats/tests/package.scala
new file mode 100644
index 0000000000..0d5cf0e3ff
--- /dev/null
+++ b/tests/shared/src/test/scala/cats/tests/package.scala
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015 Typelevel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cats
+
+package object tests extends cats.tests.compat.ScalaVersionSpecificSyntax
diff --git a/tests/src/test/scala/cats/tests/AlignSuite.scala b/tests/src/test/scala/cats/tests/AlignSuite.scala
deleted file mode 100644
index 167bc0e760..0000000000
--- a/tests/src/test/scala/cats/tests/AlignSuite.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package cats.tests
-
-import cats.Align
-import cats.kernel.laws.discipline.SemigroupTests
-
-class AlignSuite extends CatsSuite {
- {
- val optionSemigroup = Align.semigroup[Option, Int]
- checkAll("Align[Option].semigroup", SemigroupTests[Option[Int]](optionSemigroup).semigroup)
-
- val listSemigroup = Align.semigroup[List, String]
- checkAll("Align[List].semigroup", SemigroupTests[List[String]](listSemigroup).semigroup)
- }
-}
diff --git a/tests/src/test/scala/cats/tests/BifoldableSuite.scala b/tests/src/test/scala/cats/tests/BifoldableSuite.scala
deleted file mode 100644
index 18809faf77..0000000000
--- a/tests/src/test/scala/cats/tests/BifoldableSuite.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package cats.tests
-
-import cats.Bifoldable
-import cats.laws.discipline.{BifoldableTests, SerializableTests}
-import cats.syntax.either._
-import cats.syntax.eq._
-
-class BifoldableSuite extends CatsSuite {
- type EitherEither[A, B] = Either[Either[A, B], Either[A, B]]
- val eitherComposeEither: Bifoldable[EitherEither] =
- Bifoldable[Either].compose[Either]
-
- checkAll("Either compose Either", BifoldableTests(eitherComposeEither).bifoldable[Int, Int, Int])
- checkAll("Bifoldable[Either compose Either]", SerializableTests.serializable(eitherComposeEither))
-
- test("bifold works for 2 monoids") {
- assert(Bifoldable[Either].bifold(Either.right[Int, String]("something")) === ((0, "something")))
- assert(Bifoldable[Either].bifold(Either.left[Int, String](5)) === ((5, "")))
- }
-}
diff --git a/tests/src/test/scala/cats/tests/BifunctorSuite.scala b/tests/src/test/scala/cats/tests/BifunctorSuite.scala
deleted file mode 100644
index 534e3b6e8b..0000000000
--- a/tests/src/test/scala/cats/tests/BifunctorSuite.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package cats.tests
-
-import cats.{Bifunctor, Functor}
-import cats.laws.discipline.{BifunctorTests, FunctorTests, SerializableTests}
-
-class BifunctorSuite extends CatsSuite {
- type Tuple2Either[A, B] = (Either[A, B], Either[A, B])
- val tuple2ComposeEither: Bifunctor[Tuple2Either] =
- Bifunctor[Tuple2].compose[Either]
-
- checkAll("Tuple2 compose Either",
- BifunctorTests(tuple2ComposeEither).bifunctor[Int, Int, Int, String, String, String]
- )
- checkAll("Bifunctor[Tuple2 compose Either]", SerializableTests.serializable(tuple2ComposeEither))
-
- {
- type LeftFunctor[A] = (Either[A, Int], Either[A, Int])
- implicit val leftFunctor: Functor[LeftFunctor] = tuple2ComposeEither.leftFunctor
- checkAll("Bifunctor[Tuple2 compose Either].leftFunctor", FunctorTests[LeftFunctor].functor[Int, Int, Int])
- }
-
- {
- type RightFunctor[A] = (Either[Int, A], Either[Int, A])
- implicit val leftFunctor: Functor[RightFunctor] = tuple2ComposeEither.rightFunctor
- checkAll("Bifunctor[Tuple2 compose Either].rightFunctor", FunctorTests[RightFunctor].functor[Int, Int, Int])
- }
-}
diff --git a/tests/src/test/scala/cats/tests/BitSetSuite.scala b/tests/src/test/scala/cats/tests/BitSetSuite.scala
deleted file mode 100644
index 48caeb483b..0000000000
--- a/tests/src/test/scala/cats/tests/BitSetSuite.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package cats.tests
-
-import cats.syntax.show._
-import org.scalacheck.Arbitrary
-import org.scalacheck.Arbitrary.arbitrary
-import scala.collection.immutable.BitSet
-import cats.syntax.eq._
-import org.scalacheck.Prop._
-
-class BitSetSuite extends CatsSuite {
- implicit val arbitraryBitSet: Arbitrary[BitSet] =
- Arbitrary(arbitrary[List[Short]].map(ns => BitSet(ns.map(_ & 0xffff): _*)))
-
- test("show BitSet") {
- assert(BitSet(1, 1, 2, 3).show === "BitSet(1, 2, 3)")
- assert(BitSet.empty.show === "BitSet()")
-
- forAll { (fs: BitSet) =>
- assert(fs.show === (fs.toString))
- }
- }
-
-}
diff --git a/tests/src/test/scala/cats/tests/BitraverseSuite.scala b/tests/src/test/scala/cats/tests/BitraverseSuite.scala
deleted file mode 100644
index bf4f35159f..0000000000
--- a/tests/src/test/scala/cats/tests/BitraverseSuite.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package cats.tests
-
-import cats.Bitraverse
-import cats.laws.discipline.{BitraverseTests, SerializableTests}
-
-class BitraverseSuite extends CatsSuite {
- type EitherTuple2[A, B] = Either[(A, B), (A, B)]
- val eitherComposeTuple2: Bitraverse[EitherTuple2] =
- Bitraverse[Either].compose[Tuple2]
-
- checkAll("Either compose Tuple2",
- BitraverseTests(eitherComposeTuple2).bitraverse[Option, Int, Int, Int, String, String, String]
- )
- checkAll("Bitraverse[Either compose Tuple2]", SerializableTests.serializable(eitherComposeTuple2))
-}
diff --git a/tests/src/test/scala/cats/tests/BoundedEnumerableSuite.scala b/tests/src/test/scala/cats/tests/BoundedEnumerableSuite.scala
deleted file mode 100644
index 2f570a15d5..0000000000
--- a/tests/src/test/scala/cats/tests/BoundedEnumerableSuite.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package cats.tests
-
-import cats.kernel.BoundedEnumerable
-import cats.syntax.eq._
-
-class BoundedEnumerableSuite extends CatsSuite {
-
- test("membersAscending") {
- assert(BoundedEnumerable[Boolean].membersAscending.toList === (List(false, true)))
- }
-
- test("membersDescending") {
- assert(BoundedEnumerable[Boolean].membersDescending.toList === (List(true, false)))
- }
-
- test("cycleNext") {
- assert(BoundedEnumerable[Boolean].cycleNext(false) === true)
- }
-
- test("cyclePrevious") {
- assert(BoundedEnumerable[Boolean].cyclePrevious(false) === true)
- }
-
-}
diff --git a/tests/src/test/scala/cats/tests/CategorySuite.scala b/tests/src/test/scala/cats/tests/CategorySuite.scala
deleted file mode 100644
index bfeb001e84..0000000000
--- a/tests/src/test/scala/cats/tests/CategorySuite.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package cats.tests
-
-import cats.Endo
-import cats.arrow.Category
-import cats.kernel.laws.discipline.MonoidTests
-import cats.laws.discipline.{MiniInt, MonoidKTests, SerializableTests}
-import cats.laws.discipline.eq.catsLawsEqForFn1Exhaustive
-import cats.laws.discipline.arbitrary.{catsLawsArbitraryForMiniInt, catsLawsCogenForMiniInt}
-
-class CategorySuite extends CatsSuite {
- val functionCategory = Category[Function1]
-
- checkAll("Category[Function1].algebraK", MonoidKTests[Endo](functionCategory.algebraK).monoidK[MiniInt])
- checkAll("Category[Function1].algebraK", SerializableTests.serializable(functionCategory.algebraK))
-
- val functionAlgebra = functionCategory.algebra[MiniInt]
- checkAll("Category[Function1].algebra[MiniInt]", MonoidTests[Endo[MiniInt]](functionAlgebra).monoid)
-}
diff --git a/tests/src/test/scala/cats/tests/ComposeSuite.scala b/tests/src/test/scala/cats/tests/ComposeSuite.scala
deleted file mode 100644
index 7be951615d..0000000000
--- a/tests/src/test/scala/cats/tests/ComposeSuite.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package cats.tests
-
-import cats.Endo
-import cats.arrow.Compose
-import cats.kernel.laws.discipline.SemigroupTests
-import cats.laws.discipline.{MiniInt, SemigroupKTests, SerializableTests}
-import cats.laws.discipline.eq.catsLawsEqForFn1Exhaustive
-import cats.laws.discipline.arbitrary._
-import cats.syntax.compose._
-
-class ComposeSuite extends CatsSuite {
- val functionCompose = Compose[Function1]
-
- checkAll("Compose[Function1].algebraK", SemigroupKTests[Endo](functionCompose.algebraK).semigroupK[MiniInt])
- checkAll("Compose[Function1].algebraK", SerializableTests.serializable(functionCompose.algebraK))
-
- val functionAlgebra = functionCompose.algebra[MiniInt]
- checkAll("Compose[Function1].algebra[MiniInt]", SemigroupTests[Endo[MiniInt]](functionAlgebra).semigroup)
-
- test("syntax") {
- assertEquals((((_: Int) + 1) <<< ((_: Int) / 2))(2), 2)
- assertEquals((((_: Int) + 1) >>> ((_: Int) / 2))(5), 3)
- }
-}
diff --git a/tests/src/test/scala/cats/tests/DurationSuite.scala b/tests/src/test/scala/cats/tests/DurationSuite.scala
deleted file mode 100644
index a967476bdf..0000000000
--- a/tests/src/test/scala/cats/tests/DurationSuite.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package cats.tests
-
-import cats.Show
-import cats.laws.discipline.SerializableTests
-import scala.concurrent.duration.{Duration, DurationInt}
-import cats.syntax.eq._
-
-class DurationSuite extends CatsSuite {
- checkAll("Show[Duration]", SerializableTests.serializable(Show[Duration]))
-
- test("show works for FiniteDuration") {
- assert(Show[Duration].show(23.minutes) === "23 minutes")
- }
-
- test("show works for non-finite durations") {
- assert(Show[Duration].show(Duration.Inf) === "Duration.Inf")
- assert(Show[Duration].show(Duration.MinusInf) === "Duration.MinusInf")
- assert(Show[Duration].show(Duration.Undefined) === "Duration.Undefined")
- }
-}
diff --git a/tests/src/test/scala/cats/tests/EqSuite.scala b/tests/src/test/scala/cats/tests/EqSuite.scala
deleted file mode 100644
index 589241745b..0000000000
--- a/tests/src/test/scala/cats/tests/EqSuite.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package cats.tests
-
-import cats.{Contravariant, ContravariantMonoidal, ContravariantSemigroupal, Invariant, Semigroupal}
-import cats.kernel.Eq
-import cats.kernel.laws.discipline.SerializableTests
-import cats.laws.discipline.{ContravariantMonoidalTests, MiniInt}
-import cats.laws.discipline.arbitrary._
-import cats.laws.discipline.eq._
-
-class EqSuite extends CatsSuite {
- Invariant[Eq]
- Contravariant[Eq]
- Semigroupal[Eq]
- ContravariantSemigroupal[Eq]
-
- checkAll("Eq", ContravariantMonoidalTests[Eq].contravariantMonoidal[MiniInt, Boolean, Boolean])
- checkAll("ContravariantMonoidal[Eq]", SerializableTests.serializable(ContravariantMonoidal[Eq]))
-
-}
diff --git a/tests/src/test/scala/cats/tests/EquivSuite.scala b/tests/src/test/scala/cats/tests/EquivSuite.scala
deleted file mode 100644
index f8757dc7b0..0000000000
--- a/tests/src/test/scala/cats/tests/EquivSuite.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package cats.tests
-
-import cats.{Contravariant, ContravariantMonoidal, ContravariantSemigroupal, Invariant, Semigroupal}
-import cats.laws.discipline.arbitrary._
-import cats.laws.discipline._
-import cats.laws.discipline.eq._
-
-class EquivSuite extends CatsSuite {
-
- Invariant[Equiv]
- Contravariant[Equiv]
- Semigroupal[Equiv]
- ContravariantSemigroupal[Equiv]
- ContravariantMonoidal[Equiv]
-
- checkAll("Contravariant[Equiv]", ContravariantTests[Equiv].contravariant[MiniInt, Int, Boolean])
- checkAll("Semigroupal[Equiv]", SemigroupalTests[Equiv].semigroupal[MiniInt, Boolean, Boolean])
- checkAll("ContravariantMonoidal[Equiv]",
- ContravariantMonoidalTests[Equiv].contravariantMonoidal[MiniInt, Boolean, Boolean]
- )
- checkAll("ContravariantMonoidal[Equiv]", SerializableTests.serializable(ContravariantMonoidal[Equiv]))
-}
diff --git a/tests/src/test/scala/cats/tests/EvidenceSuite.scala b/tests/src/test/scala/cats/tests/EvidenceSuite.scala
deleted file mode 100644
index 5cd6f7fb79..0000000000
--- a/tests/src/test/scala/cats/tests/EvidenceSuite.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package cats.tests
-
-import cats.evidence._
-
-class EvidenceSuite extends CatsSuite {
-
- test("Is / Leibniz") {
-
- def cast1[A, B](as: List[A])(implicit ev: A Is B): List[B] =
- ev.substitute(as)
- cast1[Int, Int](1 :: 2 :: 3 :: Nil)
-
- def cast2[A, B](as: List[A])(implicit ev: Leibniz[A, B]): List[B] =
- ev.substitute(as)
- cast2[Int, Int](1 :: 2 :: 3 :: Nil)
-
- }
-
-}
diff --git a/tests/src/test/scala/cats/tests/FiniteDurationSuite.scala b/tests/src/test/scala/cats/tests/FiniteDurationSuite.scala
deleted file mode 100644
index 584f04263a..0000000000
--- a/tests/src/test/scala/cats/tests/FiniteDurationSuite.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package cats.tests
-
-import cats.Show
-import cats.laws.discipline.SerializableTests
-import scala.concurrent.duration.{DurationInt, FiniteDuration}
-import cats.syntax.eq._
-
-class FiniteDurationSuite extends CatsSuite {
- checkAll("Show[FiniteDuration]", SerializableTests.serializable(Show[FiniteDuration]))
-
- test("show works for FiniteDuration") {
- assert(Show[FiniteDuration].show(23.minutes) === "23 minutes")
- assert(Show[FiniteDuration].show(10.seconds) === "10 seconds")
- }
-}
diff --git a/tests/src/test/scala/cats/tests/GroupSuite.scala b/tests/src/test/scala/cats/tests/GroupSuite.scala
deleted file mode 100644
index 782f025f01..0000000000
--- a/tests/src/test/scala/cats/tests/GroupSuite.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package cats.tests
-
-import cats.kernel.Group
-import cats.kernel.laws.discipline.GroupTests
-import cats.syntax.eq._
-
-class GroupSuite extends CatsSuite {
- test("combine minValue") {
- assert(Group[Int].combineN(1, Int.MinValue) === (Int.MinValue))
- }
-
- test("combine negative") {
- assert(Group[Int].combineN(1, -1) === -1)
- assert(Group[Int].combineN(1, -10) === -10)
- }
-
- test("companion object syntax") {
- assert(Group[Int].inverse(1) === -1)
- assert(Group[Int].remove(1, 2) === -1)
- }
-
- checkAll("Int", GroupTests[Int].group)
-// float and double are *not* associative, and ScalaCheck knows
-// checkAll("Double", GroupLaws[Double].group)
-// checkAll("Float", GroupLaws[Float].group)
- checkAll("Long", GroupTests[Long].group)
-}
diff --git a/tests/src/test/scala/cats/tests/HashSuite.scala b/tests/src/test/scala/cats/tests/HashSuite.scala
deleted file mode 100644
index 8bc232d841..0000000000
--- a/tests/src/test/scala/cats/tests/HashSuite.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package cats.tests
-
-import cats.{Contravariant, Invariant}
-import cats.kernel.Hash
-import cats.syntax.hash._
-
-class HashSuite extends CatsSuite {
-
- {
- Invariant[Hash]
- Contravariant[Hash]
- }
-
- assert(1.hash == 1.hashCode)
- assert("ABC".hash == "ABC".hashCode)
-
-}
diff --git a/tests/src/test/scala/cats/tests/IdSuite.scala b/tests/src/test/scala/cats/tests/IdSuite.scala
deleted file mode 100644
index f923f2a2bb..0000000000
--- a/tests/src/test/scala/cats/tests/IdSuite.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package cats.tests
-
-import cats.{Bimonad, CommutativeMonad, Id, Reducible, Traverse}
-import cats.laws.discipline._
-import cats.syntax.applicative._
-import cats.syntax.eq._
-import org.scalacheck.Prop._
-
-class IdSuite extends CatsSuite {
- implicit val iso: SemigroupalTests.Isomorphisms[Id] =
- SemigroupalTests.Isomorphisms.invariant[Id]
-
- checkAll("Id[Int]", BimonadTests[Id].bimonad[Int, Int, Int])
- checkAll("Bimonad[Id]", SerializableTests.serializable(Bimonad[Id]))
-
- checkAll("Id[Int]", CommutativeMonadTests[Id].commutativeMonad[Int, Int, Int])
- checkAll("CommutativeMonad[Id]", SerializableTests.serializable(CommutativeMonad[Id]))
-
- checkAll("Id[Int]", TraverseTests[Id].traverse[Int, Int, Int, Int, Option, Option])
- checkAll("Traverse[Id]", SerializableTests.serializable(Traverse[Id]))
-
- checkAll("Id[Int]", ReducibleTests[Id].reducible[Option, Int, Int])
- checkAll("Reducible[Id]", SerializableTests.serializable(Reducible[Id]))
-
- test("Id#apply") {
- forAll { (i: Int) =>
- val id = Id(i)
- assert(id === (i: Id[Int]))
- assert(id === i.pure[Id])
- assert(id === i)
- }
- }
-}
diff --git a/tests/src/test/scala/cats/tests/MonoidSuite.scala b/tests/src/test/scala/cats/tests/MonoidSuite.scala
deleted file mode 100644
index 0904b1883b..0000000000
--- a/tests/src/test/scala/cats/tests/MonoidSuite.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package cats.tests
-
-import cats.{Invariant, InvariantSemigroupal}
-import cats.kernel.Monoid
-import cats.syntax.eq._
-
-class MonoidSuite extends CatsSuite {
- {
- Invariant[Monoid]
- InvariantSemigroupal[Monoid]
- }
-
- test("companion object syntax") {
- assert(Monoid.empty[Int] === 0)
- assert(Monoid.isEmpty(1) === false)
- assert(Monoid.isEmpty(0) === true)
- }
-}
-
-object MonoidSuite {
- def summonInstance(): Unit = {
- Invariant[Monoid]
- ()
- }
-
-}
diff --git a/tests/src/test/scala/cats/tests/NonEmptyAlternativeSuite.scala b/tests/src/test/scala/cats/tests/NonEmptyAlternativeSuite.scala
deleted file mode 100644
index c6603fb507..0000000000
--- a/tests/src/test/scala/cats/tests/NonEmptyAlternativeSuite.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package cats.tests
-
-import cats.NonEmptyAlternative
-import cats.laws.discipline.NonEmptyAlternativeTests
-
-class NonEmptyAlternativeSuite extends CatsSuite {
- implicit val listWrapperNeAlternative: NonEmptyAlternative[ListWrapper] = ListWrapper.nonEmptyAlternative
-
- checkAll("Option[Int]", NonEmptyAlternativeTests[Option].nonEmptyAlternative[Int, Int, Int])
- checkAll("List[Int]", NonEmptyAlternativeTests[List].nonEmptyAlternative[Int, Int, Int])
- checkAll("ListWrapper[List[Int]]", NonEmptyAlternativeTests[ListWrapper].nonEmptyAlternative[Int, Int, Int])
- checkAll(
- "compose ListWrapper[List[Int]]",
- NonEmptyAlternativeTests.composed[ListWrapper, List].nonEmptyAlternative[Int, Int, Int]
- )
- checkAll(
- "compose List[ListWrapper[Int]]",
- NonEmptyAlternativeTests.composed[List, ListWrapper].nonEmptyAlternative[Int, Int, Int]
- )
- checkAll(
- "compose ListWrapper[ListWrapper[Int]]",
- NonEmptyAlternativeTests.composed[ListWrapper, ListWrapper].nonEmptyAlternative[Int, Int, Int]
- )
-}
diff --git a/tests/src/test/scala/cats/tests/OneAndSuite.scala b/tests/src/test/scala/cats/tests/OneAndSuite.scala
deleted file mode 100644
index 4b0431819b..0000000000
--- a/tests/src/test/scala/cats/tests/OneAndSuite.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package cats.tests
-
-import cats.{Alternative, Applicative, Foldable, Functor, Monad, SemigroupK, Traverse}
-import cats.data.OneAnd
-import cats.laws.discipline._
-import cats.laws.discipline.arbitrary._
-import cats.laws.discipline.SemigroupalTests.Isomorphisms
-import cats.syntax.foldable._
-import cats.syntax.eq._
-import org.scalacheck.Prop._
-import org.scalacheck.Test.Parameters
-
-class OneAndSuite extends CatsSuite {
- // Lots of collections here.. telling ScalaCheck to calm down a bit
- implicit override val scalaCheckTestParameters: Parameters =
- Parameters.default.withMinSuccessfulTests(20).withMaxSize(Parameters.default.minSize + 5)
-
- {
- implicit val traverse: Traverse[OneAnd[ListWrapper, *]] = OneAnd.catsDataTraverseForOneAnd(ListWrapper.traverse)
- checkAll("OneAnd[ListWrapper, Int] with Option",
- TraverseTests[OneAnd[ListWrapper, *]].traverse[Int, Int, Int, Int, Option, Option]
- )
- checkAll("Traverse[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Traverse[OneAnd[ListWrapper, *]]))
- }
-
- implicit val iso: Isomorphisms[OneAnd[ListWrapper, *]] =
- Isomorphisms.invariant[OneAnd[ListWrapper, *]](OneAnd.catsDataFunctorForOneAnd(ListWrapper.functor))
-
- // Test instances that have more general constraints
- {
- implicit val monad: Monad[ListWrapper] = ListWrapper.monad
- implicit val alt: Alternative[ListWrapper] = ListWrapper.alternative
- checkAll("OneAnd[ListWrapper, Int]", MonadTests[OneAnd[ListWrapper, *]].monad[Int, Int, Int])
- checkAll("MonadTests[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Monad[OneAnd[ListWrapper, *]]))
- }
-
- {
- implicit val alternative: Alternative[ListWrapper] = ListWrapper.alternative
- checkAll("OneAnd[ListWrapper, Int]", ApplicativeTests[OneAnd[ListWrapper, *]].applicative[Int, Int, Int])
- checkAll("Applicative[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Applicative[OneAnd[ListWrapper, *]]))
- }
-
- {
- implicit val functor: Functor[ListWrapper] = ListWrapper.functor
- checkAll("OneAnd[ListWrapper, Int]", FunctorTests[OneAnd[ListWrapper, *]].functor[Int, Int, Int])
- checkAll("Functor[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Functor[OneAnd[ListWrapper, *]]))
- }
-
- {
- implicit val alternative: Alternative[ListWrapper] = ListWrapper.alternative
- checkAll("OneAnd[ListWrapper, Int]", SemigroupKTests[OneAnd[ListWrapper, *]].semigroupK[Int])
- checkAll("SemigroupK[OneAnd[ListWrapper, A]]", SerializableTests.serializable(SemigroupK[OneAnd[ListWrapper, *]]))
- }
-
- {
- implicit val foldable: Foldable[ListWrapper] = ListWrapper.foldable
- checkAll("OneAnd[ListWrapper, Int]", FoldableTests[OneAnd[ListWrapper, *]].foldable[Int, Int])
- checkAll("Foldable[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Foldable[OneAnd[ListWrapper, *]]))
- }
-
- test("size is consistent with toList.size") {
- forAll { (oa: OneAnd[Vector, Int]) =>
- assert(oa.size === (oa.toList.size.toLong))
- }
- }
-
-}
diff --git a/tests/src/test/scala/cats/tests/OptionWrapper.scala b/tests/src/test/scala/cats/tests/OptionWrapper.scala
deleted file mode 100644
index 2c842bdc2e..0000000000
--- a/tests/src/test/scala/cats/tests/OptionWrapper.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package cats.tests
-
-import cats.Functor
-import cats.laws.discipline.ExhaustiveCheck
-import org.scalacheck.{Arbitrary, Cogen}
-import org.scalacheck.Arbitrary.arbitrary
-
-/**
- * Similar to [[ListWrapper]], but using `Option` instead of `List` limits the size of the structure, which can be
- * useful for limiting the space of test values to generate.
- */
-final case class OptionWrapper[A](option: Option[A]) extends AnyVal
-
-object OptionWrapper {
- val functor: Functor[OptionWrapper] = new Functor[OptionWrapper] {
- def map[A, B](fa: OptionWrapper[A])(f: A => B) = OptionWrapper(fa.option.map(f))
- }
-
- implicit def optionWrapperArbitrary[A: Arbitrary]: Arbitrary[OptionWrapper[A]] =
- Arbitrary(arbitrary[Option[A]].map(OptionWrapper.apply))
-
- implicit def optionWrapperCogen[A: Cogen]: Cogen[OptionWrapper[A]] =
- Cogen[Option[A]].contramap(_.option)
-
- implicit def catsLawsExhaustiveCheckForOptionWrapper[A](implicit
- A: ExhaustiveCheck[A]
- ): ExhaustiveCheck[OptionWrapper[A]] =
- ExhaustiveCheck.instance(ExhaustiveCheck[Option[A]].allValues.map(OptionWrapper(_)))
-}
diff --git a/tests/src/test/scala/cats/tests/OrderingSuite.scala b/tests/src/test/scala/cats/tests/OrderingSuite.scala
deleted file mode 100644
index dc17ae31fd..0000000000
--- a/tests/src/test/scala/cats/tests/OrderingSuite.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package cats.tests
-
-import cats.{Contravariant, ContravariantMonoidal, ContravariantSemigroupal, Invariant, Semigroupal}
-import cats.laws.discipline.arbitrary._
-import cats.laws.discipline._
-import cats.laws.discipline.eq._
-
-class OrderingSuite extends CatsSuite {
-
- Invariant[Ordering]
- Contravariant[Ordering]
- Semigroupal[Ordering]
- ContravariantSemigroupal[Ordering]
- ContravariantMonoidal[Ordering]
-
- checkAll("Contravariant[Ordering]", ContravariantTests[Ordering].contravariant[MiniInt, Int, Boolean])
- checkAll("Semigroupal[Ordering]", SemigroupalTests[Ordering].semigroupal[MiniInt, Boolean, Boolean])
- checkAll("ContravariantMonoidal[Ordering]",
- ContravariantMonoidalTests[Ordering].contravariantMonoidal[MiniInt, Boolean, Boolean]
- )
- checkAll("ContravariantMonoidal[Ordering]", SerializableTests.serializable(ContravariantMonoidal[Ordering]))
-}
diff --git a/tests/src/test/scala/cats/tests/PartialFunctionSuite.scala b/tests/src/test/scala/cats/tests/PartialFunctionSuite.scala
deleted file mode 100644
index d07ac57121..0000000000
--- a/tests/src/test/scala/cats/tests/PartialFunctionSuite.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package cats.tests
-import cats.arrow.{ArrowChoice, CommutativeArrow}
-import cats.kernel.laws.discipline.SerializableTests
-import cats.laws.discipline.arbitrary._
-import cats.laws.discipline.eq._
-import cats.laws.discipline.{ArrowChoiceTests, CommutativeArrowTests, MiniInt}
-
-class PartialFunctionSuite extends CatsSuite {
-
- checkAll("ArrowChoice[PartialFunction]", SerializableTests.serializable(ArrowChoice[PartialFunction]))
-
- checkAll("PartialFunction",
- ArrowChoiceTests[PartialFunction].arrowChoice[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, MiniInt]
- )
-
- checkAll("CommutativeArrow[PartialFunction]", SerializableTests.serializable(CommutativeArrow[PartialFunction]))
- checkAll(
- "PartialFunction",
- CommutativeArrowTests[PartialFunction].commutativeArrow[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, MiniInt]
- )
-
-}
diff --git a/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala b/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala
deleted file mode 100644
index 536206c21f..0000000000
--- a/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package cats.tests
-
-import cats.{Contravariant, ContravariantMonoidal, ContravariantSemigroupal, Invariant, Semigroupal}
-import cats.laws.discipline.arbitrary._
-import cats.laws.discipline._
-import cats.laws.discipline.eq._
-
-class PartialOrderingSuite extends CatsSuite {
-
- Invariant[PartialOrdering]
- Contravariant[PartialOrdering]
- Semigroupal[PartialOrdering]
- ContravariantSemigroupal[PartialOrdering]
-
- checkAll("Contravariant[PartialOrdering]", ContravariantTests[PartialOrdering].contravariant[MiniInt, Int, Boolean])
- checkAll("Semigroupal[PartialOrdering]", SemigroupalTests[PartialOrdering].semigroupal[MiniInt, Boolean, Boolean])
- checkAll("Contravariant[PartialOrdering]", SerializableTests.serializable(Contravariant[PartialOrdering]))
-
- checkAll("PartialOrdering[Int]",
- ContravariantMonoidalTests[PartialOrdering].contravariantMonoidal[MiniInt, Boolean, Boolean]
- )
- checkAll("ContravariantMonoidal[PartialOrdering]",
- SerializableTests.serializable(ContravariantMonoidal[PartialOrdering])
- )
-}
diff --git a/tests/src/test/scala/cats/tests/SemigroupKSuite.scala b/tests/src/test/scala/cats/tests/SemigroupKSuite.scala
deleted file mode 100644
index 4d366bacba..0000000000
--- a/tests/src/test/scala/cats/tests/SemigroupKSuite.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package cats.tests
-
-import cats.{Align, Alternative, SemigroupK}
-import cats.data.{Chain, Validated}
-import cats.laws.discipline.AlignTests
-import cats.laws.discipline.arbitrary._
-
-class SemigroupKSuite extends CatsSuite {
- implicit val listwrapperSemigroupK: Alternative[ListWrapper] = ListWrapper.alternative
- implicit val listwrapperAlign: Align[ListWrapper] = SemigroupK.align[ListWrapper]
- checkAll("SemigroupK[ListWrapper].align", AlignTests[ListWrapper].align[Int, Int, Int, Int])
-
- implicit val validatedAlign: Align[Validated[String, *]] = SemigroupK.align[Validated[String, *]]
- checkAll("SemigroupK[Validated].align", AlignTests[Validated[String, *]].align[Int, Int, Int, Int])
-
- implicit val chainAlign: Align[Chain] = SemigroupK.align[Chain]
- checkAll("SemigroupK[Chain].align", AlignTests[Chain].align[Int, Int, Int, Int])
-}
diff --git a/tests/src/test/scala/cats/tests/SemigroupSuite.scala b/tests/src/test/scala/cats/tests/SemigroupSuite.scala
deleted file mode 100644
index bf8b6490e8..0000000000
--- a/tests/src/test/scala/cats/tests/SemigroupSuite.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package cats.tests
-
-import cats.{Invariant, InvariantMonoidal, Semigroupal}
-import cats.kernel.Semigroup
-import cats.syntax.eq._
-import cats.kernel.laws.discipline.SemigroupTests
-import org.scalacheck.Prop._
-
-class SemigroupSuite extends CatsSuite {
- {
- Invariant[Semigroup]
- Semigroupal[Semigroup]
- InvariantMonoidal[Semigroup]
- }
-
- {
- Invariant[Semigroup]
- Semigroupal[Semigroup]
- InvariantMonoidal[Semigroup]
- }
-
- property("Semigroup.instance creates a Semigroup from the given function") {
- val mult: (Int, Int) => Int = (a, b) => a * b
- val add: (Int, Int) => Int = (a, b) => a + b
-
- forAll { (a: Int, b: Int) =>
- assert(Semigroup.instance(mult).combine(a, b) === (a * b))
- assert(Semigroup.instance(add).combine(a, b) === (a + b))
- }
- }
-
- {
- val S = Semigroup.first[Int]
- checkAll("Semigroup.first", SemigroupTests[Int](S).semigroup)
- }
-
- {
- val S = Semigroup.last[Int]
- checkAll("Semigroup.last", SemigroupTests[Int](S).semigroup)
- }
-}
diff --git a/tests/src/test/scala/cats/tests/ShowSuite.scala b/tests/src/test/scala/cats/tests/ShowSuite.scala
deleted file mode 100644
index a501a1a8ad..0000000000
--- a/tests/src/test/scala/cats/tests/ShowSuite.scala
+++ /dev/null
@@ -1,85 +0,0 @@
-package cats.tests
-
-import cats.{Contravariant, Show}
-import cats.Show.ContravariantShow
-import cats.kernel.Order
-import cats.syntax.show._
-import cats.laws.discipline.{ContravariantTests, MiniInt, SerializableTests}
-import cats.laws.discipline.arbitrary._
-import cats.laws.discipline.eq._
-import java.util.concurrent.TimeUnit
-import scala.collection.immutable.Seq
-import scala.concurrent.duration.{Duration, FiniteDuration}
-
-class ShowSuite extends CatsSuite {
- checkAll("Contravariant[Show]", ContravariantTests[Show].contravariant[MiniInt, Int, Boolean])
- checkAll("Contravariant[Show]", SerializableTests.serializable(Contravariant[Show]))
-
- sealed trait TimeOfDay
- case object Morning extends TimeOfDay
- object TimeOfDay {
- implicit val showTimeOfDay: Show[TimeOfDay] = Show.show { case Morning => "morning" }
- }
-
- test("show string interpolator") {
- case class Cat(name: String)
- object Cat {
- implicit val showCat: Show[Cat] = Show.show(_.name)
- }
- val tod: TimeOfDay = Morning
- val cat = Cat("Whiskers")
-
- assertEquals("Good morning, Whiskers!", show"Good $tod, $cat!")
-
- assertEquals("Good morning, Whiskers!", show"Good $tod, ${List(cat).head}!")
- }
-
- test("show string interpolator and contravariance") {
- val tod: Morning.type = Morning
-
- assertEquals("Good morning", show"Good $tod")
- }
-
- test("contravariant show is not ambiguous when both FiniteDuration's and Duration's instances are in scope") {
- implicitly[ContravariantShow[FiniteDuration]]
- implicitly[ContravariantShow[Duration]]
- }
-
- test("show interpolation works when both FiniteDuration's and Duration's instances are in scope") {
- show"instance resolution is not ambiguous for ${FiniteDuration(3L, TimeUnit.SECONDS)}"
- show"instance resolution is not ambiguous for ${Duration(3L, TimeUnit.SECONDS)}"
- }
-
- test("show interpolation with Seq subtypes isn't ambiguous") {
- implicitly[ContravariantShow[Seq[Int]]]
- implicitly[ContravariantShow[List[Int]]]
- implicitly[ContravariantShow[Vector[Int]]]
-
- val goodmornings = Seq("guten Tag", "good morning", "bonjour")
- assertEquals(show"$goodmornings", "List(guten Tag, good morning, bonjour)")
- assertEquals(show"${goodmornings.toList}", "List(guten Tag, good morning, bonjour)")
- assertEquals(show"${goodmornings.toVector}", "Vector(guten Tag, good morning, bonjour)")
- }
-}
-
-final class ShowSuite2 extends munit.FunSuite {
-
- test(
- "contravariant show for FiniteDuration can be inferred when importing both duration's and finiteDuration's instances"
- ) {
-
- implicitly[Order[Duration]]
- implicitly[Order[FiniteDuration]]
-
- implicitly[ContravariantShow[FiniteDuration]]
- }
-
- test("all the Duration's and FiniteDuration's instances can be correctly inferred when importing implicits") {
-
- implicitly[Order[Duration]]
- implicitly[Order[FiniteDuration]]
-
- implicitly[ContravariantShow[Duration]]
- implicitly[ContravariantShow[FiniteDuration]]
- }
-}
diff --git a/tests/src/test/scala/cats/tests/SplitSuite.scala b/tests/src/test/scala/cats/tests/SplitSuite.scala
deleted file mode 100644
index bffddabda7..0000000000
--- a/tests/src/test/scala/cats/tests/SplitSuite.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package cats.tests
-
-import cats.syntax.arrow._
-
-class SplitSuite extends CatsSuite {
- test("syntax") {
- val f = ((_: Int) + 1).split((_: Int) / 2)
- assertEquals(f((1, 2)), (2, 1))
- }
-}
diff --git a/tests/src/test/scala/cats/tests/Spooky.scala b/tests/src/test/scala/cats/tests/Spooky.scala
deleted file mode 100644
index bc1ce9d003..0000000000
--- a/tests/src/test/scala/cats/tests/Spooky.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package cats.tests
-
-/**
- * Class for spooky side-effects and action-at-a-distance.
- *
- * It is basically a mutable counter that can be used to measure how
- * many times an otherwise pure function is being evaluated.
- */
-class Spooky(var counter: Int = 0) {
- def increment(): Unit = counter += 1
-}
diff --git a/tests/src/test/scala/cats/tests/SyntaxSerializationSuite.scala b/tests/src/test/scala/cats/tests/SyntaxSerializationSuite.scala
deleted file mode 100644
index 18e71d1e89..0000000000
--- a/tests/src/test/scala/cats/tests/SyntaxSerializationSuite.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package cats.tests
-
-import cats.laws.discipline.SerializableTests
-import cats.syntax.either._
-
-/**
- * Test that our syntax implicits are serializable.
- */
-class SyntaxSerializationSuite extends CatsSuite {
- checkAll(
- "Tuple3SemigroupalOps[Option, Boolean, Int, Long]",
- SerializableTests.serializable(
- cats.syntax.all.catsSyntaxTuple3Semigroupal[Option, Boolean, Int, Long]((None, None, None))
- )
- )
-
- checkAll("SemigroupalOps[Option, Int]",
- SerializableTests.serializable(cats.syntax.all.catsSyntaxSemigroupal[Option, Int](None))
- )
-
- checkAll(
- "Tuple3ParallelOps[Either[String, *], Boolean, Int, Long]",
- SerializableTests.serializable(
- cats.syntax.all.catsSyntaxTuple3Parallel(("a".asLeft[Boolean], "b".asLeft[Int], "c".asLeft[Long]))
- )
- )
-}
diff --git a/tests/src/test/scala/cats/tests/TailRecSuite.scala b/tests/src/test/scala/cats/tests/TailRecSuite.scala
deleted file mode 100644
index 65bb97eafa..0000000000
--- a/tests/src/test/scala/cats/tests/TailRecSuite.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package cats.tests
-
-import cats.{Defer, Monad}
-import cats.kernel.Eq
-import cats.laws.discipline.{DeferTests, MonadTests, SerializableTests}
-import scala.util.control.TailCalls.{done, tailcall, TailRec}
-import org.scalacheck.{Arbitrary, Cogen, Gen}
-import org.scalacheck.Arbitrary.arbitrary
-
-class TailRecSuite extends CatsSuite {
-
- implicit def tailRecArb[A: Arbitrary: Cogen]: Arbitrary[TailRec[A]] =
- Arbitrary(
- Gen.frequency(
- (3, arbitrary[A].map(done(_))),
- (1, Gen.lzy(arbitrary[(A, A => TailRec[A])].map { case (a, fn) => tailcall(fn(a)) })),
- (1, Gen.lzy(arbitrary[(TailRec[A], A => TailRec[A])].map { case (a, fn) => a.flatMap(fn) }))
- )
- )
-
- implicit def eqTailRec[A: Eq]: Eq[TailRec[A]] =
- Eq.by[TailRec[A], A](_.result)
-
- checkAll("TailRec[Int]", MonadTests[TailRec].monad[Int, Int, Int])
- checkAll("Monad[TailRec]", SerializableTests.serializable(Monad[TailRec]))
-
- checkAll("TailRec[Int]", DeferTests[TailRec].defer[Int])
- checkAll("Defer[TailRec]", SerializableTests.serializable(Defer[TailRec]))
-}
diff --git a/tests/src/test/scala/cats/tests/TraverseFilterSuite.scala b/tests/src/test/scala/cats/tests/TraverseFilterSuite.scala
deleted file mode 100644
index bd1e447c31..0000000000
--- a/tests/src/test/scala/cats/tests/TraverseFilterSuite.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package cats.tests
-
-import cats.data.Chain
-import cats.instances.all._
-import cats.laws.discipline.arbitrary.catsLawsArbitraryForChain
-import cats.syntax.eq._
-import cats.syntax.foldable._
-import cats.syntax.traverseFilter._
-import cats.{Traverse, TraverseFilter}
-import org.scalacheck.Arbitrary
-import org.scalacheck.Prop.forAll
-
-import scala.collection.immutable.Queue
-
-abstract class TraverseFilterSuite[F[_]: TraverseFilter](name: String)(implicit
- ArbFInt: Arbitrary[F[Int]],
- ArbFString: Arbitrary[F[String]]
-) extends CatsSuite {
-
- implicit def T: Traverse[F] = implicitly[TraverseFilter[F]].traverse
-
- test(s"TraverseFilter[$name].ordDistinct") {
- forAll { (fa: F[Int]) =>
- fa.ordDistinct.toList === fa.toList.distinct
- }
- }
-
- test(s"TraverseFilter[$name].hashDistinct") {
- forAll { (fa: F[String]) =>
- fa.hashDistinct.toList === fa.toList.distinct
- }
- }
-}
-
-class TraverseFilterListSuite extends TraverseFilterSuite[List]("list")
-
-class TraverseFilterVectorSuite extends TraverseFilterSuite[Vector]("vector")
-
-class TraverseFilterChainSuite extends TraverseFilterSuite[Chain]("chain")
-
-class TraverseFilterQueueSuite extends TraverseFilterSuite[Queue]("queue")
-
-class TraverseFilterStreamSuite extends TraverseFilterSuite[Stream]("stream")
diff --git a/tests/src/test/scala/cats/tests/TraverseSuite.scala b/tests/src/test/scala/cats/tests/TraverseSuite.scala
deleted file mode 100644
index 21ea7bad5f..0000000000
--- a/tests/src/test/scala/cats/tests/TraverseSuite.scala
+++ /dev/null
@@ -1,87 +0,0 @@
-package cats.tests
-
-import cats.{Applicative, Eval, Traverse}
-import cats.kernel.compat.scalaVersionSpecific._
-import cats.syntax.foldable._
-import cats.syntax.functor._
-import cats.syntax.traverse._
-import org.scalacheck.Arbitrary
-import cats.syntax.eq._
-import org.scalacheck.Prop._
-
-@suppressUnusedImportWarningForScalaVersionSpecific
-abstract class TraverseSuite[F[_]: Traverse](name: String)(implicit ArbFInt: Arbitrary[F[Int]]) extends CatsSuite {
-
- test(s"Traverse[$name].zipWithIndex") {
- forAll { (fa: F[Int]) =>
- assert(fa.zipWithIndex.toList === (fa.toList.zipWithIndex))
- }
- }
-
- test(s"Traverse[$name].mapWithIndex") {
- forAll { (fa: F[Int], fn: ((Int, Int)) => Int) =>
- assert(fa.mapWithIndex((a, i) => fn((a, i))).toList === (fa.toList.zipWithIndex.map(fn)))
- }
- }
-
- test(s"Traverse[$name].traverseWithIndexM") {
- forAll { (fa: F[Int], fn: ((Int, Int)) => (Int, Int)) =>
- val left = fa.traverseWithIndexM((a, i) => fn((a, i))).fmap(_.toList)
- val (xs, values) = fa.toList.zipWithIndex.map(fn).unzip
- assert(left === ((xs.combineAll, values)))
- }
- }
-
- test(s"Traverse[$name].traverse matches traverse_ with Option") {
- forAll { (fa: F[Int], fn: Int => Option[Int]) =>
- assert(Applicative[Option].void(fa.traverse(fn)) == fa.traverse_(fn))
- }
- }
-
-}
-
-object TraverseSuite {
- // forces testing of the underlying implementation (avoids overridden methods)
- abstract class Underlying[F[_]: Traverse](name: String)(implicit ArbFInt: Arbitrary[F[Int]])
- extends TraverseSuite(s"$name (underlying)")(proxyTraverse[F], ArbFInt)
-
- // proxies a traverse instance so we can test default implementations
- // to achieve coverage using default datatype instances
- private def proxyTraverse[F[_]: Traverse]: Traverse[F] =
- new Traverse[F] {
- def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B =
- Traverse[F].foldLeft(fa, b)(f)
- def foldRight[A, B](fa: F[A], lb: cats.Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
- Traverse[F].foldRight(fa, lb)(f)
- def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] =
- Traverse[F].traverse(fa)(f)
- }
-}
-
-class TraverseListSuite extends TraverseSuite[List]("List")
-class TraverseStreamSuite extends TraverseSuite[Stream]("Stream")
-class TraverseVectorSuite extends TraverseSuite[Vector]("Vector")
-
-class TraverseListSuiteUnderlying extends TraverseSuite.Underlying[List]("List")
-class TraverseStreamSuiteUnderlying extends TraverseSuite.Underlying[Stream]("Stream")
-class TraverseVectorSuiteUnderlying extends TraverseSuite.Underlying[Vector]("Vector")
-
-class TraverseSuiteAdditional extends CatsSuite with ScalaVersionSpecificTraverseSuite {
-
- def checkZipWithIndexedStackSafety[F[_]](fromRange: Range => F[Int])(implicit F: Traverse[F]): Unit = {
- F.zipWithIndex(fromRange(1 to 70000))
- ()
- }
-
- test("Traverse[List].zipWithIndex stack safety") {
- checkZipWithIndexedStackSafety[List](_.toList)
- }
-
- test("Traverse[Stream].zipWithIndex stack safety") {
- checkZipWithIndexedStackSafety[Stream](_.toStream)
- }
-
- test("Traverse[Vector].zipWithIndex stack safety") {
- checkZipWithIndexedStackSafety[Vector](_.toVector)
- }
-}
diff --git a/tests/src/test/scala/cats/tests/UnorderedTraverseSuite.scala b/tests/src/test/scala/cats/tests/UnorderedTraverseSuite.scala
deleted file mode 100644
index 8d8e63477d..0000000000
--- a/tests/src/test/scala/cats/tests/UnorderedTraverseSuite.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package cats.tests
-
-import cats.Id
-import cats.syntax.unorderedTraverse._
-import cats.syntax.eq._
-import org.scalacheck.Prop._
-
-class UnorderedTraverseSuite extends CatsSuite {
- test("UnorderedTraverse[Set[Int]].unorderedTraverse via syntax") {
- forAll { (ins: Set[Int]) =>
- assert(ins.unorderedTraverse(in => in: Id[Int]).toList.sorted === (ins.toList.sorted))
- }
- }
-}
diff --git a/tests/src/test/scala/cats/tests/WriterSuite.scala b/tests/src/test/scala/cats/tests/WriterSuite.scala
deleted file mode 100644
index 0638b49281..0000000000
--- a/tests/src/test/scala/cats/tests/WriterSuite.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package cats.tests
-
-import cats.data.Writer
-import cats.syntax.applicative._
-import cats.syntax.writer._
-import cats.syntax.eq._
-import org.scalacheck.Prop._
-
-class WriterSuite extends CatsSuite {
- test("pure syntax creates a writer with an empty log") {
- forAll { (result: String) =>
- type Logged[A] = Writer[List[Int], A]
- assert(result.pure[Logged] === (Writer(List.empty[Int], result)))
- }
- }
-
- test("tell syntax creates a writer with a unit result") {
- forAll { (log: List[Int]) =>
- assert(log.tell === (Writer(log, ())))
- }
- }
-
- test("writer syntax creates a writer with the specified result and log") {
- forAll { (result: String, log: List[Int]) =>
- assert(result.writer(log) === (Writer(log, result)))
- }
- }
-
- test("catsDataCommutativeMonadForWriterT and catsDataTraverseForWriterTId instances are not ambiguous") {
- import cats.Functor
- Functor[Writer[Int, *]]
- }
-}
diff --git a/version.sbt b/version.sbt
deleted file mode 100644
index 90ecc00089..0000000000
--- a/version.sbt
+++ /dev/null
@@ -1 +0,0 @@
-ThisBuild / version := "2.7.0"