Stop using stack in Travis (#121)

The travis cache appears to be broken (probably due to the nightly stack?), but it just means CI takes like half an hour now. Since I already build on stack, I'm pretty sure it's fine --- also this will give a sanity check against accidentally breaking cabal build plans.

This improves CI times from ~30 minutes down to ~2.
This commit is contained in:
Sandy Maguire 2019-06-18 12:36:38 -04:00 committed by GitHub
parent 78d0c4905a
commit c3d3cc24f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 196 additions and 230 deletions

View File

@ -1,44 +1,36 @@
# Adapted from https://github.com/commercialhaskell/stack
language: c
sudo: false
language: haskell
dist: trusty
cache:
directories:
- $HOME/.ghc
- $HOME/.cabal
- $HOME/.stack
- .stack-work
directories:
- $HOME/.cabal/store
cabal: "2.4"
matrix:
include:
# ghc 8.6.3
- env: STACK='stack --resolver=lts-13.0' CACHE_NAME=8.6.3
addons: {apt: {packages: [libgmp-dev]}}
# nightly
- env: STACK='stack --resolver=nightly' CACHE_NAME=nightly
addons: {apt: {packages: [libgmp-dev]}}
# Use the resolver in stack.yaml
- env: STACK=stack CACHE_NAME=stack-linux
addons: {apt: {packages: [libgmp-dev]}}
- env: STACK=stack CACHE_NAME=stack-osx
os: osx
addons: {apt: {packages: [libgmp-dev]}}
- ghc: "8.6.3"
# - ghc: "8.4.4"
# - ghc: "8.2.2"
# - ghc: "8.0.2"
# - ghc: "7.10.3"
# - ghc: "7.8.4"
# - ghc: "7.6.3"
install:
- unset CC
- export PATH=$HOME/.local/bin:/opt/ghc/$GHCVER/bin:$PATH
- ./.travis/install-stack.sh
- cabal --version
- ghc --version
script:
- echo "$($STACK ghc -- --version) [$($STACK ghc -- --print-project-git-commit-id 2> /dev/null || echo '?')]"
- GHC_OPTIONS="-Werror"
- |
set -ex
$STACK --no-terminal build --ghc-options="$GHC_OPTIONS"
$STACK test --ghc-options="$GHC_OPTIONS"
set +ex
- cabal v2-update
- cabal v2-build
- cabal v2-test --enable-test
- cabal new-haddock
- cabal check
- cabal sdist # tests that a source-distribution can be generated
# Check that the resulting source distribution can be built & installed.
# If there are no other `.tar.gz` files in `dist`, this can be even simpler:
# `cabal install --force-reinstalls dist/*-*.tar.gz`
- SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
(cd dist && cabal install --force-reinstalls "$SRC_TGZ")

View File

@ -1,29 +0,0 @@
#!/bin/sh
# Adapted from https://github.com/commercialhaskell/stack
set -eux
travis_retry() {
cmd=$*
$cmd || (sleep 2 && $cmd) || (sleep 10 && $cmd)
}
fetch_stack_osx() {
curl -skL https://www.stackage.org/stack/osx-x86_64 | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin;
}
fetch_stack_linux() {
curl -sL https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack';
}
# We need stack to generate cabal files with precise bounds, even for cabal
# builds.
mkdir -p ~/.local/bin;
if [ "$(uname)" = "Darwin" ]; then
travis_retry fetch_stack_osx
else
travis_retry fetch_stack_linux
fi
travis_retry $STACK --no-terminal setup;

View File

@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: 3f16c72f17a2b211f296fedc1a93db88198f2f05fc66b94d1e277319c3a76613
-- hash: 8215f1fa69bdaae106988aaf84f4a2dd2338231d1fc11ddf7dd30a9d8b61449b
name: polysemy
version: 0.4.0.0
@ -98,6 +98,7 @@ test-suite polysemy-test
InspectorSpec
OutputSpec
ThEffectSpec
TypeErrors
Paths_polysemy
hs-source-dirs:
test

View File

@ -1,173 +1,8 @@
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
module DoctestSpec where
import Test.DocTest
import Test.Hspec
-- $setup
-- >>> default ()
-- >>> :m +Polysemy
-- >>> :m +Polysemy.Output
-- >>> :m +Polysemy.Reader
-- >>> :m +Polysemy.Resource
-- >>> :m +Polysemy.State
-- >>> :m +Polysemy.Trace
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- foo :: Sem r ()
-- foo = put ()
-- :}
-- ...
-- ... Ambiguous use of effect 'State'
-- ...
-- ... (Member (State ()) r) ...
-- ...
ambiguousMonoState = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- foo :: Sem r ()
-- foo = put 5
-- :}
-- ...
-- ... Ambiguous use of effect 'State'
-- ...
-- ... (Member (State s0) r) ...
-- ...
-- ... 's0' directly...
-- ...
ambiguousPolyState = ()
--------------------------------------------------------------------------------
-- |
-- TODO(sandy): should this mention 'Reader i' or just 'Reader'?
--
-- >>> :{
-- interpret @Reader $ \case
-- Ask -> undefined
-- :}
-- ...
-- ... 'Reader i' is higher-order, but 'interpret' can help only
-- ... with first-order effects.
-- ...
-- ... 'interpretH' instead.
-- ...
interpretBadFirstOrder = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- runFoldMapOutput
-- :: forall o m r a
-- . Monoid m
-- => (o -> m)
-- -> Sem (Output o ': r) a
-- -> Sem r (m, a)
-- runFoldMapOutput f = runState mempty . reinterpret $ \case
-- Output o -> modify (<> f o)
-- :}
-- ...
-- ... Probable cause: ...reinterpret... is applied to too few arguments
-- ...
tooFewArgumentsReinterpret = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- let reinterpretScrub :: Sem (Output Int ': m) a -> Sem (State Bool ': Trace ': m) a
-- reinterpretScrub = undefined
-- foo :: Sem '[Output Int] ()
-- foo = pure ()
-- foo' = reinterpretScrub foo
-- foo'' = runState True foo'
-- foo''' = runTraceIO foo''
-- in runM foo'''
-- :}
-- ...
-- ... Ambiguous use of effect 'Lift'
-- ...
-- ... add (Member (Lift IO) '[]) ...
-- ...
--
-- PROBLEM: We're trying to run more effects than exist in the eff row. This is
-- indeed a problem, but the error message isn't helpful.
--
-- SOLUTION: Add a special case to `AmbiguousSend` when `r ~ '[]`.
runningTooManyEffects'WRONG = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- foo :: Sem (State Int ': r) ()
-- foo = put ()
-- :}
-- ...
-- ... Ambiguous use of effect 'State'
-- ...
-- ... (Member (State ()) State Int : r) ...
-- ...
--
-- PROBLEM: There should be parentheses around `State Int : r`
--
-- SOLUTION: Emit parens only when the effect row is of the form `e1 ': ...`
missingParens'WRONG = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- let foo :: Member Resource r => Sem r ()
-- foo = undefined
-- in runM $ runResourceInIO foo
-- :}
-- ...
-- ... Ambiguous use of effect 'Lift'
-- ...
-- ... (Member (Lift IO) r0) ...
-- ...
-- ... Could not deduce: (Member Resource r1)
-- ...
--
-- PROBLEM: This error is totally bogus. We forgot to give an argument to
-- 'runResourceInIO'. For comparison, the standard error GHC gives in this case
-- is significantly more helpful:
--
-- <interactive>:192:13: error:
-- • Couldn't match expected type Sem '[Lift m] a
-- with actual type Sem (Resource : r0) a0 -> Sem r0 a0
-- • Probable cause: runResourceInIO is applied to too few arguments
-- In the second argument of ($), namely runResourceInIO foo
-- In the expression: runM $ runResourceInIO foo
-- In the expression:
-- let
-- foo :: Member Resource r => Sem r ()
-- foo = undefined
-- in runM $ runResourceInIO foo
-- • Relevant bindings include
-- it :: m a (bound at <interactive>:190:2)
-- <interactive>:192:29: error:
-- • Couldn't match expected type Sem r0 x -> IO x
-- with actual type Sem r1 ()
-- • In the first argument of runResourceInIO, namely foo
-- In the second argument of ($), namely runResourceInIO foo
-- In the expression: runM $ runResourceInIO foo
--
--
-- SOLUTION: Honestly I'm not sure!
missingArgumentToRunResourceInIO'WRONG = ()
spec :: Spec
spec = parallel $ describe "Error messages" $ it "should pass the doctest" $ doctest
[ "-isrc/"
@ -186,7 +21,7 @@ spec = parallel $ describe "Error messages" $ it "should pass the doctest" $ doc
, "-XTypeFamilies"
, "-XUnicodeSyntax"
, "test/DoctestSpec.hs"
, "test/TypeErrors.hs"
-- Modules that are explicitly imported for this test must be listed here
, "src/Polysemy.hs"

167
test/TypeErrors.hs Normal file
View File

@ -0,0 +1,167 @@
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
module TypeErrors where
-- $setup
-- >>> default ()
-- >>> :m +Polysemy
-- >>> :m +Polysemy.Output
-- >>> :m +Polysemy.Reader
-- >>> :m +Polysemy.Resource
-- >>> :m +Polysemy.State
-- >>> :m +Polysemy.Trace
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- foo :: Sem r ()
-- foo = put ()
-- :}
-- ...
-- ... Ambiguous use of effect 'State'
-- ...
-- ... (Member (State ()) r) ...
-- ...
ambiguousMonoState = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- foo :: Sem r ()
-- foo = put 5
-- :}
-- ...
-- ... Ambiguous use of effect 'State'
-- ...
-- ... (Member (State s0) r) ...
-- ...
-- ... 's0' directly...
-- ...
ambiguousPolyState = ()
--------------------------------------------------------------------------------
-- |
-- TODO(sandy): should this mention 'Reader i' or just 'Reader'?
--
-- >>> :{
-- interpret @Reader $ \case
-- Ask -> undefined
-- :}
-- ...
-- ... 'Reader i' is higher-order, but 'interpret' can help only
-- ... with first-order effects.
-- ...
-- ... 'interpretH' instead.
-- ...
interpretBadFirstOrder = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- runFoldMapOutput
-- :: forall o m r a
-- . Monoid m
-- => (o -> m)
-- -> Sem (Output o ': r) a
-- -> Sem r (m, a)
-- runFoldMapOutput f = runState mempty . reinterpret $ \case
-- Output o -> modify (<> f o)
-- :}
-- ...
-- ... Probable cause: ...reinterpret... is applied to too few arguments
-- ...
tooFewArgumentsReinterpret = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- let reinterpretScrub :: Sem (Output Int ': m) a -> Sem (State Bool ': Trace ': m) a
-- reinterpretScrub = undefined
-- foo :: Sem '[Output Int] ()
-- foo = pure ()
-- foo' = reinterpretScrub foo
-- foo'' = runState True foo'
-- foo''' = runTraceIO foo''
-- in runM foo'''
-- :}
-- ...
-- ... Ambiguous use of effect 'Lift'
-- ...
-- ... add (Member (Lift IO) '[]) ...
-- ...
--
-- PROBLEM: We're trying to run more effects than exist in the eff row. This is
-- indeed a problem, but the error message isn't helpful.
--
-- SOLUTION: Add a special case to `AmbiguousSend` when `r ~ '[]`.
runningTooManyEffects'WRONG = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- foo :: Sem (State Int ': r) ()
-- foo = put ()
-- :}
-- ...
-- ... Ambiguous use of effect 'State'
-- ...
-- ... (Member (State ()) State Int : r) ...
-- ...
--
-- PROBLEM: There should be parentheses around `State Int : r`
--
-- SOLUTION: Emit parens only when the effect row is of the form `e1 ': ...`
missingParens'WRONG = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- let foo :: Member Resource r => Sem r ()
-- foo = undefined
-- in runM $ runResourceInIO foo
-- :}
-- ...
-- ... Ambiguous use of effect 'Lift'
-- ...
-- ... (Member (Lift IO) r0) ...
-- ...
-- ... Could not deduce: (Member Resource r1)
-- ...
--
-- PROBLEM: This error is totally bogus. We forgot to give an argument to
-- 'runResourceInIO'. For comparison, the standard error GHC gives in this case
-- is significantly more helpful:
--
-- <interactive>:192:13: error:
-- • Couldn't match expected type Sem '[Lift m] a
-- with actual type Sem (Resource : r0) a0 -> Sem r0 a0
-- • Probable cause: runResourceInIO is applied to too few arguments
-- In the second argument of ($), namely runResourceInIO foo
-- In the expression: runM $ runResourceInIO foo
-- In the expression:
-- let
-- foo :: Member Resource r => Sem r ()
-- foo = undefined
-- in runM $ runResourceInIO foo
-- • Relevant bindings include
-- it :: m a (bound at <interactive>:190:2)
-- <interactive>:192:29: error:
-- • Couldn't match expected type Sem r0 x -> IO x
-- with actual type Sem r1 ()
-- • In the first argument of runResourceInIO, namely foo
-- In the second argument of ($), namely runResourceInIO foo
-- In the expression: runM $ runResourceInIO foo
--
--
-- SOLUTION: Honestly I'm not sure!
missingArgumentToRunResourceInIO'WRONG = ()