git.iko.soy/fused-effects-squeal
on master help sign in
Initial commit
commit2e744ac3c6e5bd26f53c351a3b97417487d11873 authoriko <ilyakooo0@gmail.com> dateFri 17 Jan 2020, 20:53 (7 years ago)
9 files changed+552
LICENSE+30 README.md+1 Setup.hs+2 fused-effects-squeal.cabal+39 package.yaml+46 src/Control/Carrier/Orphans.hs+45 src/Control/Carrier/Squeal.hs+172 src/Control/Effect/Squeal.hs+146 stack.yaml+71
LICENSEnew file+30
@@ -0,0 +1,30 @@
1+Copyright Ilya Kostyuchenko (c) 2020
2+
3+All rights reserved.
4+
5+Redistribution and use in source and binary forms, with or without
6+modification, are permitted provided that the following conditions are met:
7+
8+ * Redistributions of source code must retain the above copyright
9+ notice, this list of conditions and the following disclaimer.
10+
11+ * Redistributions in binary form must reproduce the above
12+ copyright notice, this list of conditions and the following
13+ disclaimer in the documentation and/or other materials provided
14+ with the distribution.
15+
16+ * Neither the name of Ilya Kostyuchenko nor the names of other
17+ contributors may be used to endorse or promote products derived
18+ from this software without specific prior written permission.
19+
20+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
README.mdnew file+1
@@ -0,0 +1 @@
1+# fused-effects-squeal
Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
fused-effects-squeal.cabalnew file+39
@@ -0,0 +1,39 @@
1+cabal-version: 1.12
2+
3+-- This file has been generated from package.yaml by hpack version 0.31.2.
4+--
5+-- see: https://github.com/sol/hpack
6+--
7+-- hash: 71b37a35dcdd207118aa15d0413b9360e39eab5cfff06f6bf9e9cecc9fc81dad
8+
9+name: fused-effects-squeal
10+version: 0.1.0.0
11+category: Web
12+homepage: https://github.com/ilyakooo0/fused-effects-squeal#readme
13+author: Ilya Kostyuchenko
14+maintainer: ilyakooo0@gmail.com
15+copyright: Ilya Kostyuchenko
16+license: BSD3
17+license-file: LICENSE
18+build-type: Simple
19+extra-source-files:
20+ README.md
21+
22+library
23+ exposed-modules:
24+ Control.Carrier.Squeal
25+ Control.Effect.Squeal
26+ other-modules:
27+ Control.Carrier.Orphans
28+ Paths_fused_effects_squeal
29+ hs-source-dirs:
30+ src
31+ default-extensions: DataKinds DeriveFunctor DeriveGeneric FlexibleContexts FlexibleInstances GADTs GeneralizedNewtypeDeriving MultiParamTypeClasses OverloadedLabels OverloadedStrings TypeApplications TypeOperators UndecidableInstances ScopedTypeVariables PolyKinds DerivingStrategies StandaloneDeriving LambdaCase
32+ build-depends:
33+ base >=4.7 && <5
34+ , fused-effects
35+ , squeal-postgresql
36+ , unliftio
37+ , unliftio-core
38+ , unliftio-pool
39+ default-language: Haskell2010
package.yamlnew file+46
@@ -0,0 +1,46 @@
1+name: fused-effects-squeal
2+version: 0.1.0.0
3+#synopsis:
4+#description:
5+homepage: https://github.com/ilyakooo0/fused-effects-squeal#readme
6+license: BSD3
7+author: Ilya Kostyuchenko
8+maintainer: ilyakooo0@gmail.com
9+copyright: Ilya Kostyuchenko
10+category: Web
11+extra-source-files:
12+- README.md
13+
14+dependencies:
15+- base >= 4.7 && < 5
16+- fused-effects
17+- squeal-postgresql
18+- unliftio-core
19+- unliftio
20+- unliftio-pool
21+
22+library:
23+ source-dirs: src
24+ exposed-modules:
25+ - Control.Carrier.Squeal
26+ - Control.Effect.Squeal
27+
28+default-extensions:
29+- DataKinds
30+- DeriveFunctor
31+- DeriveGeneric
32+- FlexibleContexts
33+- FlexibleInstances
34+- GADTs
35+- GeneralizedNewtypeDeriving
36+- MultiParamTypeClasses
37+- OverloadedLabels
38+- OverloadedStrings
39+- TypeApplications
40+- TypeOperators
41+- UndecidableInstances
42+- ScopedTypeVariables
43+- PolyKinds
44+- DerivingStrategies
45+- StandaloneDeriving
46+- LambdaCase
src/Control/Carrier/Orphans.hsnew file+45
@@ -0,0 +1,45 @@
1+{-# OPTIONS_GHC -Wno-orphans #-}
2+
3+module Control.Carrier.Orphans
4+ (
5+ )
6+where
7+
8+import Control.Carrier.Interpret
9+import Control.Carrier.Lift
10+import Control.Carrier.Reader
11+import qualified Control.Carrier.Trace.Ignoring as TI
12+import qualified Control.Carrier.Trace.Printing as TP
13+import Control.Monad.IO.Unlift
14+
15+instance MonadUnliftIO m => MonadUnliftIO (LiftC m) where
16+ askUnliftIO = LiftC $ withUnliftIO $ \u -> return (UnliftIO (unliftIO u . runM))
17+ {-# INLINE askUnliftIO #-}
18+
19+ withRunInIO inner = LiftC $ withRunInIO $ \run' -> inner (run' . runM)
20+ {-# INLINE withRunInIO #-}
21+
22+instance MonadUnliftIO m => MonadUnliftIO (ReaderC r m) where
23+ askUnliftIO = ReaderC $ \r -> withUnliftIO $ \u -> pure (UnliftIO (\(ReaderC x) -> unliftIO u (x r)))
24+ {-# INLINE askUnliftIO #-}
25+
26+ withRunInIO inner = ReaderC $ \r -> withRunInIO $ \go -> inner (go . runReader r)
27+ {-# INLINE withRunInIO #-}
28+
29+instance MonadUnliftIO m => MonadUnliftIO (InterpretC s sig m) where
30+ askUnliftIO = InterpretC $ withUnliftIO $ \u -> return (UnliftIO (\(InterpretC m) -> unliftIO u m))
31+ {-# INLINE askUnliftIO #-}
32+ withRunInIO inner = InterpretC $ withRunInIO $ \run' -> inner (\(InterpretC m) -> run' m)
33+ {-# INLINE withRunInIO #-}
34+
35+instance MonadUnliftIO m => MonadUnliftIO (TI.TraceC m) where
36+ askUnliftIO = TI.TraceC $ withUnliftIO $ \u -> return (UnliftIO (unliftIO u . TI.runTrace))
37+ {-# INLINE askUnliftIO #-}
38+ withRunInIO inner = TI.TraceC $ withRunInIO $ \run' -> inner (run' . TI.runTrace)
39+ {-# INLINE withRunInIO #-}
40+
41+instance MonadUnliftIO m => MonadUnliftIO (TP.TraceC m) where
42+ askUnliftIO = TP.TraceC $ withUnliftIO $ \u -> return (UnliftIO (unliftIO u . TP.runTrace))
43+ {-# INLINE askUnliftIO #-}
44+ withRunInIO inner = TP.TraceC $ withRunInIO $ \run' -> inner (run' . TP.runTrace)
45+ {-# INLINE withRunInIO #-}
src/Control/Carrier/Squeal.hsnew file+172
@@ -0,0 +1,172 @@
1+module Control.Carrier.Squeal
2+ ( DBConnection,
3+ runSquealWithConn,
4+ runSquealWithConnRethrow,
5+ runSquealWithConn',
6+ SquealC (..),
7+ getSquealPool,
8+ runSqueal',
9+ runSqueal,
10+ runSquealPool,
11+ runSquealRethrow,
12+ SquealPool (..),
13+ module Control.Algebra,
14+ )
15+where
16+
17+import Control.Algebra
18+import Control.Carrier.Orphans ()
19+import Control.Effect.Squeal
20+import Control.Monad.IO.Unlift
21+import Data.Functor
22+import qualified Squeal.PostgreSQL as Sq
23+import UnliftIO
24+import UnliftIO.Pool
25+
26+type DBConnection (schemas :: SchemasType) = K Connection schemas
27+
28+newtype SquealC schemas m k = SquealC {unSquealC :: DBConnection schemas -> m k}
29+
30+instance Functor m => Functor (SquealC schemas m) where
31+ fmap f (SquealC mk) = SquealC $ (fmap . fmap) f mk
32+
33+instance Applicative m => Applicative (SquealC schemas m) where
34+ pure x = SquealC $ \_ -> pure x
35+ (SquealC mklhs) <*> (SquealC mkrhs) = SquealC $ \r -> mklhs r <*> mkrhs r
36+
37+instance Monad m => Monad (SquealC schemas m) where
38+ (SquealC mk) >>= f = SquealC $ \r -> mk r >>= (runSquealWithConn' r . f)
39+
40+instance MonadIO m => MonadIO (SquealC schemas m) where
41+ liftIO = SquealC . const . liftIO
42+
43+instance MonadUnliftIO m => MonadUnliftIO (SquealC schemas m) where
44+ withRunInIO inner = SquealC $ \r -> withRunInIO (\f -> inner (f . runSquealWithConn' r))
45+
46+instance (MonadUnliftIO m, Algebra sig m) => Algebra (Squeal schemas :+: sig) (SquealC schemas m) where
47+ alg (L (ManipulateParams man x mk)) = SquealC $ \r -> do
48+ res <- flip evalPQ r $ Sq.manipulateParams man x
49+ runSquealWithConn' r $ mk res
50+ alg (L (TraversePrepared man x mk)) = SquealC $ \r -> do
51+ res <- flip evalPQ r $ Sq.traversePrepared man x
52+ runSquealWithConn' r $ mk res
53+ alg (L (TraversePrepared_ man x mk)) = SquealC $ \r -> do
54+ flip evalPQ r $ Sq.traversePrepared_ man x
55+ runSquealWithConn' r mk
56+ alg (R other) = SquealC $ \r -> alg . hmap (runSquealWithConn' r) $ other
57+
58+-- | Run a squeal session using the given database connection without a transaction and without any error handling. You probably shouldn't use this.
59+runSquealWithConn' :: DBConnection schemas -> SquealC schemas m k -> m k
60+runSquealWithConn' r (SquealC mk) = mk r
61+
62+-- | Run a squeal session using the given database connection, transaction mode and error handler.
63+runSquealWithConn ::
64+ MonadUnliftIO m =>
65+ DBConnection schemas ->
66+ Maybe TransactionMode ->
67+ (SquealException -> m k) ->
68+ SquealC schemas m k ->
69+ m k
70+runSquealWithConn db tr er mk =
71+ handleSqueal er $ maybe id (transactionallyRetry' db) tr (runSquealWithConn' db mk)
72+ where
73+ transactionallyRetry' ::
74+ (MonadUnliftIO m) =>
75+ DBConnection schemas ->
76+ TransactionMode ->
77+ m x ->
78+ m x
79+ transactionallyRetry' conn mode tx = mask $ \restore ->
80+ loop . try $ do
81+ x <- restore tx
82+ flip evalPQ conn $ Sq.manipulate_ commit
83+ return x
84+ where
85+ loop attempt = do
86+ flip evalPQ conn $ Sq.manipulate_ $ begin mode
87+ attempt >>= \case
88+ Left (PQException (PQState _ (Just "40001") _)) -> do
89+ flip evalPQ conn $ Sq.manipulate_ rollback
90+ loop attempt
91+ Left err -> do
92+ flip evalPQ conn $ Sq.manipulate_ rollback
93+ throwIO err
94+ Right x -> return x
95+
96+-- | Run a squeal session using the given database connection and transaction mode. Errors will not be handled.
97+runSquealWithConnRethrow ::
98+ MonadUnliftIO m =>
99+ DBConnection schemas ->
100+ Maybe TransactionMode ->
101+ SquealC schemas m k ->
102+ m k
103+runSquealWithConnRethrow db tr = runSquealWithConn db tr throwIO
104+
105+newtype SquealPoolC schemas m k = SquealPoolC {unSquealPoolC :: Pool (DBConnection schemas) -> m k}
106+
107+instance Functor m => Functor (SquealPoolC schemas m) where
108+ fmap f (SquealPoolC mk) = SquealPoolC $ (fmap . fmap) f mk
109+
110+instance Applicative m => Applicative (SquealPoolC schemas m) where
111+ pure x = SquealPoolC $ const $ pure x
112+ (SquealPoolC mklhs) <*> (SquealPoolC mkrhs) = SquealPoolC $ \r -> mklhs r <*> mkrhs r
113+
114+instance Monad m => Monad (SquealPoolC schemas m) where
115+ (SquealPoolC mk) >>= f = SquealPoolC $ \r -> mk r >>= (($ r) . unSquealPoolC . f)
116+
117+instance MonadIO m => MonadIO (SquealPoolC schemas m) where
118+ liftIO = SquealPoolC . const . liftIO
119+
120+instance MonadUnliftIO m => MonadUnliftIO (SquealPoolC schemas m) where
121+ withRunInIO inner = SquealPoolC $ \r -> withRunInIO (\f -> inner (f . ($ r) . unSquealPoolC))
122+
123+runSquealPool :: Pool (DBConnection schemas) -> SquealPoolC schemas m k -> m k
124+runSquealPool conn (SquealPoolC f) = f conn
125+
126+instance Algebra sig m => Algebra (SquealPool schemas :+: sig) (SquealPoolC schemas m) where
127+ alg (L (GetSquealPool mk)) = SquealPoolC $ \r -> runSquealPool r $ mk r
128+ alg (R other) = SquealPoolC $ \r -> alg . hmap (runSquealPool r) $ other
129+
130+newtype SquealPool schemas m k = GetSquealPool (Pool (DBConnection schemas) -> m k)
131+
132+instance Functor m => Functor (SquealPool schemas m) where
133+ fmap f (GetSquealPool mk) = GetSquealPool ((fmap . fmap) f mk)
134+
135+instance HFunctor (SquealPool schemas) where
136+ hmap f (GetSquealPool mk) = GetSquealPool (fmap f mk)
137+
138+instance Effect (SquealPool schemas) where
139+ thread ctx f (GetSquealPool mk) = GetSquealPool $ \y -> f (ctx $> mk y)
140+
141+getSquealPool :: Has (SquealPool schemas) sig m => m (Pool (DBConnection schemas))
142+getSquealPool = send $ GetSquealPool pure
143+
144+-- | Run a squeal session picking a database connection from the connection pool without a transaction and without any error handling. You probably shouldn't use this.
145+runSqueal' ::
146+ (MonadUnliftIO m, Has (SquealPool schemas) sig m) =>
147+ SquealC schemas m k ->
148+ m k
149+runSqueal' = runSqueal Nothing throwIO
150+
151+-- | Run a squeal session picking a database connection from the connection pool with the given transaction mode and error handler.
152+runSqueal ::
153+ (MonadUnliftIO m, Has (SquealPool schemas) sig m) =>
154+ Maybe TransactionMode ->
155+ (SquealException -> m k) ->
156+ SquealC schemas m k ->
157+ m k
158+runSqueal tr er mk = do
159+ pool <- getSquealPool
160+ withResource pool $ \db ->
161+ runSquealWithConn db tr er mk
162+
163+-- | Run a squeal session picking a database connection from the connection pool with the given transaction mode. Errors will not be handled.
164+runSquealRethrow ::
165+ (MonadUnliftIO m, Has (SquealPool schemas) sig m) =>
166+ Maybe TransactionMode ->
167+ SquealC schemas m k ->
168+ m k
169+runSquealRethrow tr mk = do
170+ pool <- getSquealPool
171+ withResource pool $ \db ->
172+ runSquealWithConn db tr throwIO mk
src/Control/Effect/Squeal.hsnew file+146
@@ -0,0 +1,146 @@
1+module Control.Effect.Squeal
2+ ( Squeal (..),
3+ manipulateParams,
4+ manipulateParams_,
5+ manipulate,
6+ manipulate_,
7+ runQueryParams,
8+ runQuery,
9+ traversePrepared,
10+ forPrepared,
11+ traversePrepared_,
12+ forPrepared_,
13+
14+ -- * Reexports
15+ module Sq,
16+ module Control.Algebra,
17+ )
18+where
19+
20+import Control.Algebra
21+import Data.Functor
22+import Squeal.PostgreSQL as Sq hiding
23+ ( Has,
24+ forPrepared,
25+ forPrepared_,
26+ manipulate,
27+ manipulateParams,
28+ manipulateParams_,
29+ manipulate_,
30+ runQuery,
31+ runQueryParams,
32+ traversePrepared,
33+ traversePrepared_,
34+ )
35+
36+data Squeal (schemas :: SchemasType) m k where
37+ ManipulateParams ::
38+ Sq.ToParams x params =>
39+ Sq.Manipulation '[] schemas params ys ->
40+ x ->
41+ (Sq.K Sq.Result ys -> m k) ->
42+ Squeal schemas m k
43+ TraversePrepared ::
44+ (Sq.ToParams x params, Traversable list) =>
45+ Sq.Manipulation '[] schemas params ys ->
46+ list x ->
47+ (list (Sq.K Sq.Result ys) -> m k) ->
48+ Squeal schemas m k
49+ TraversePrepared_ ::
50+ (Sq.ToParams x params, Foldable list) =>
51+ Sq.Manipulation '[] schemas params '[] ->
52+ list x ->
53+ m k ->
54+ Squeal schemas m k
55+
56+instance Functor m => Functor (Squeal schemas m) where
57+ fmap f (ManipulateParams man x mk) = ManipulateParams man x ((fmap . fmap) f mk)
58+ fmap f (TraversePrepared man x mk) = TraversePrepared man x ((fmap . fmap) f mk)
59+ fmap f (TraversePrepared_ man x mk) = TraversePrepared_ man x (fmap f mk)
60+
61+instance HFunctor (Squeal schemas) where
62+ hmap f (ManipulateParams man x mk) = ManipulateParams man x (fmap f mk)
63+ hmap f (TraversePrepared man x mk) = TraversePrepared man x (fmap f mk)
64+ hmap f (TraversePrepared_ man x mk) = TraversePrepared_ man x (f mk)
65+
66+instance Effect (Squeal schemas) where
67+ thread ctx f (ManipulateParams man x mk) = ManipulateParams man x $ \y -> f (ctx $> mk y)
68+ thread ctx f (TraversePrepared man x mk) = TraversePrepared man x $ \y -> f (ctx $> mk y)
69+ thread ctx f (TraversePrepared_ man x mk) = TraversePrepared_ man x $ f (ctx $> mk)
70+
71+-- | See 'Sq.manipulateParams' from @squeal-postgresql@.
72+manipulateParams ::
73+ (Has (Squeal schemas) sig m, Sq.ToParams x params) =>
74+ Sq.Manipulation '[] schemas params ys ->
75+ x ->
76+ m (Sq.K Sq.Result ys)
77+manipulateParams man x = send $ ManipulateParams man x pure
78+
79+-- | See 'Sq.manipulateParams_' from @squeal-postgresql@.
80+manipulateParams_ ::
81+ (Has (Squeal schemas) sig m, Sq.ToParams x params) =>
82+ Sq.Manipulation '[] schemas params ys ->
83+ x ->
84+ m ()
85+manipulateParams_ man x = manipulateParams man x $> ()
86+
87+-- | See 'Sq.manipulate' from @squeal-postgresql@.
88+manipulate ::
89+ Has (Squeal schemas) sig m =>
90+ Sq.Manipulation '[] schemas '[] ys ->
91+ m (Sq.K Sq.Result ys)
92+manipulate man = manipulateParams man ()
93+
94+-- | See 'Sq.manipulate_' from @squeal-postgresql@.
95+manipulate_ ::
96+ Has (Squeal schemas) sig m =>
97+ Sq.Manipulation '[] schemas '[] ys ->
98+ m ()
99+manipulate_ man = manipulate_ man $> ()
100+
101+-- | See 'Sq.runQueryParams' from @squeal-postgresql@.
102+runQueryParams ::
103+ (Has (Squeal schemas) sig m, Sq.ToParams x params) =>
104+ Sq.Query '[] '[] schemas params ys ->
105+ x ->
106+ m (Sq.K Sq.Result ys)
107+runQueryParams = manipulateParams . Sq.queryStatement
108+
109+-- | See 'Sq.runQuery' from @squeal-postgresql@.
110+runQuery ::
111+ Has (Squeal schemas) sig m =>
112+ Sq.Query '[] '[] schemas '[] ys ->
113+ m (Sq.K Sq.Result ys)
114+runQuery q = runQueryParams q ()
115+
116+-- | See 'Sq.traversePrepared' from @squeal-postgresql@.
117+traversePrepared ::
118+ (Sq.ToParams x params, Traversable list, Has (Squeal schemas) sig m) =>
119+ Sq.Manipulation '[] schemas params ys ->
120+ list x ->
121+ m (list (Sq.K Sq.Result ys))
122+traversePrepared man l = send $ TraversePrepared man l pure
123+
124+-- | See 'Sq.forPrepared' from @squeal-postgresql@.
125+forPrepared ::
126+ (Sq.ToParams x params, Traversable list, Has (Squeal schemas) sig m) =>
127+ list x ->
128+ Sq.Manipulation '[] schemas params ys ->
129+ m (list (Sq.K Sq.Result ys))
130+forPrepared = flip traversePrepared
131+
132+-- | See 'Sq.traversePrepared_' from @squeal-postgresql@.
133+traversePrepared_ ::
134+ (Sq.ToParams x params, Foldable list, Has (Squeal schemas) sig m) =>
135+ Sq.Manipulation '[] schemas params '[] ->
136+ list x ->
137+ m ()
138+traversePrepared_ man l = send $ TraversePrepared_ man l (pure ())
139+
140+-- | See 'Sq.forPrepared_' from @squeal-postgresql@.
141+forPrepared_ ::
142+ (Sq.ToParams x params, Foldable list, Has (Squeal schemas) sig m) =>
143+ list x ->
144+ Sq.Manipulation '[] schemas params '[] ->
145+ m ()
146+forPrepared_ = flip traversePrepared_
stack.yamlnew file+71
@@ -0,0 +1,71 @@
1+# This file was automatically generated by 'stack init'
2+#
3+# Some commonly used options have been documented as comments in this file.
4+# For advanced use and comprehensive documentation of the format, please see:
5+# https://docs.haskellstack.org/en/stable/yaml_configuration/
6+
7+# Resolver to choose a 'specific' stackage snapshot or a compiler version.
8+# A snapshot resolver dictates the compiler version and the set of packages
9+# to be used for project dependencies. For example:
10+#
11+# resolver: lts-3.5
12+# resolver: nightly-2015-09-21
13+# resolver: ghc-7.10.2
14+#
15+# The location of a snapshot can be provided as a file or url. Stack assumes
16+# a snapshot provided as a file might change, whereas a url resource does not.
17+#
18+# resolver: ./custom-snapshot.yaml
19+# resolver: https://example.com/snapshots/2018-01-01.yaml
20+resolver: lts-14.20
21+
22+# User packages to be built.
23+# Various formats can be used as shown in the example below.
24+#
25+# packages:
26+# - some-directory
27+# - https://example.com/foo/bar/baz-0.0.2.tar.gz
28+# subdirs:
29+# - auto-update
30+# - wai
31+packages:
32+- .
33+# Dependency packages to be pulled from upstream that are not in the resolver.
34+# These entries can reference officially published versions as well as
35+# forks / in-progress versions pinned to a git hash. For example:
36+#
37+# extra-deps:
38+# - acme-missiles-0.3
39+# - git: https://github.com/commercialhaskell/stack.git
40+# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
41+#
42+extra-deps:
43+- squeal-postgresql-0.5.2.0
44+- fused-effects-1.0.0.0
45+
46+# Override default flag values for local packages and extra-deps
47+# flags: {}
48+
49+# Extra package databases containing global packages
50+# extra-package-dbs: []
51+
52+# Control whether we use the GHC we find on the path
53+# system-ghc: true
54+#
55+# Require a specific version of stack, using version ranges
56+# require-stack-version: -any # Default
57+# require-stack-version: ">=2.1"
58+#
59+# Override the architecture used by stack, especially useful on Windows
60+# arch: i386
61+# arch: x86_64
62+#
63+# Extra directories used by stack for building
64+# extra-include-dirs: [/path/to/dir]
65+# extra-lib-dirs: [/path/to/dir]
66+#
67+# Allow a newer minor version of GHC than the snapshot specifies
68+# compiler-check: newer-minor
69+
70+ghc-options:
71+ "$locals": -ddump-to-file -ddump-hi -fwarn-unused-binds -fwarn-unused-imports -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Wpartial-fields -Werror=missing-home-modules -Wmissing-home-modules -Widentities -Wredundant-constraints -Wmissing-export-lists