cgaebel / stm-conduit Goto Github PK
View Code? Open in Web Editor NEWSTM-based channels for conduits.
License: BSD 3-Clause "New" or "Revised" License
STM-based channels for conduits.
License: BSD 3-Clause "New" or "Revised" License
In a StackOverflow question, a user ended up confused by the behavior of sinkTBMChan, namely that it automatically closes the channel after the sink is completed. I'd recommend changing stm-conduit so that the channel is not automatically closed. This would fit with other parts of the conduit ecosystem, where a Sink never closes a resource allocated elsewhere (compare sinkFile and sinkHandle, for example).
If you want to do this in a verbose, backwards-compatible manner, I'd recommend:
Looking at the gatherFrom
code (pasted below for convenient), I've got a scatter
function that starts up a TCP server. Ideally, this TCP server would be restarted in the case gatherFrom
is called again due to exception handling at the outer level. Of course, it became obvious that this wasn't possible due to the bound listening socket never being closed. I'm not immediately sure of the best way to handle this, though one possibility is perhaps rewriting the code to use withAsync
. However, even if possible, I'm not even sure that would be desirable for all use cases.
gatherFrom :: (MonadIO m, MonadUnliftIO m)
=> Int -- ^ Size of the queue to create
-> (TBQueue o -> m ()) -- ^ Action that generates output values
-> ConduitT () o m ()
gatherFrom size scatter = do
chan <- liftIO $ newTBQueueIO (fromIntegral size)
worker <- lift $ async (scatter chan)
gather worker chan
where
gather worker chan = do
(xs, mres) <- liftIO $ atomically $ do
xs <- whileM (not <$> isEmptyTBQueue chan) (readTBQueue chan)
(xs,) <$> pollSTM worker
traverse_ yield xs
case mres of
Just (Left e) -> liftIO $ throwIO (e :: SomeException)
Just (Right r) -> return r
Nothing -> gather worker chan
I'm unable to compile Data.Conduit.Async.Composition which has a bare
import Conduit
https://github.com/cgaebel/stm-conduit/blob/master/Data/Conduit/Async/Composition.hs#L30
AFAICT, the module name should be Data.Conduit:
http://hackage.haskell.org/package/conduit-1.2.6.6/docs/Data-Conduit.html
I'm quite new to Haskell but I guess this is not supposed to happen
Using the example code below when using the plain conduit source the memory usage stays constant but with mergeSources
it keeps growing. Even when doing a merge with a single source.
main :: IO ()
main = do
let
sqrts = yieldMany [1..] .| mapC sqrt .| printC
source <- mergeSources (replicate 2 sqrts) 16
-- source <- return sqrts
runConduitRes $ source .| sinkNull
This is useful in a server context (for instance). The only difference from gatherFrom
is in the alternatives for case mres
so that it now continues to check for values on the TBQueue
(even if it is empty at some point). Given that, rather than having two functions, maybe having a parameter to gatherFrom
to determine which case mres
to use (wait forever or not) would be ok, but I don't have a strong preference on how to organize it.
gatherForever :: forall m o. (MonadIO m, MonadUnliftIO m)
=> Int -- ^ Size of the queue to create
-> (TBQueue o -> m ()) -- ^ Action that generates output values
-> ConduitT () o m ()
gatherForever size scatter = do
chan <- liftIO $ newTBQueueIO (fromIntegral size)
worker <- lift $ async (scatter chan)
res <- gather worker chan
pure res
where
gather :: Async b -> TBQueue o -> ConduitT i o m b
gather worker chan = do
(xs :: [o], mres) <- liftIO $ atomically $ do
xs <- whileM (not <$> isEmptyTBQueue chan) (readTBQueue chan)
(xs,) <$> pollSTM worker
traverse_ yield xs
case mres of
Just (Left e) -> liftIO $ throwIO (e :: SomeException)
_ -> gather worker chan
When using $$&
and the upstream conduit throws an exception with throwError
, we get a deadlock.
I can trigger an error of the type Main.hs: thread blocked indefinitely in an STM transaction
with the following code:
module Main
( main
) where
import qualified Data.Conduit.Combinators as C
import qualified Data.Conduit.List as CL
import Data.Conduit ((=$=))
import Data.Conduit.Async (($$&))
import Control.Monad.Except
import Control.Monad.Trans.Resource
data ErrorType = TriggerError deriving (Show, Eq)
main = runExceptT . runResourceT $
(C.yieldMany [1 :: Int, 2, 3] >> throwError TriggerError)
=$= CL.map (+1)
$$& C.print
The build fails on GHC 8:
[4 of 5] Compiling Data.Conduit.Async.Composition ( Data/Conduit/Async/Composition.hs, dist/build/Data/Conduit/Async/Composition.o )
Data/Conduit/Async/Composition.hs:207:42: error:
Not in scope: type constructor or class ‘Constraint’
Full build log:
these derivations will be built:
/nix/store/jyz1m745y8nhxk7l2h05c2p2arihq42p-stm-conduit-2.7.0.drv
building path(s) ‘/nix/store/nwjx03jf33pb5lgy9bcsqv717wxfbvsk-stm-conduit-2.7.0’
setupCompilerEnvironmentPhase
Build with /nix/store/9ycqyik6sknsicdjhawn49yxv7m93mnc-ghc-8.0.0.20160204.
unpacking sources
unpacking source archive /nix/store/acbdmm448dhnw55qnb4f3qbdi5n1haky-stm-conduit-2.7.0.tar.gz
source root is stm-conduit-2.7.0
setting SOURCE_DATE_EPOCH to timestamp 1449558767 of file stm-conduit-2.7.0/test/Test.hs
patching sources
Run jailbreak-cabal to lift version restrictions on build inputs.
compileBuildDriverPhase
setupCompileFlags: -package-db=/tmp/nix-build-stm-conduit-2.7.0.drv-0/package.conf.d -j1 -threa
ded
[1 of 1] Compiling Main ( Setup.lhs, /tmp/nix-build-stm-conduit-2.7.0.drv-0/Main.o
)
Linking Setup ...
configuring
configureFlags: --verbose --prefix=/nix/store/nwjx03jf33pb5lgy9bcsqv717wxfbvsk-stm-conduit-2.7.
0 --libdir=$prefix/lib/$compiler --libsubdir=$pkgid --with-gcc=gcc --package-db=/tmp/nix-build-
stm-conduit-2.7.0.drv-0/package.conf.d --ghc-option=-optl=-Wl,-rpath=/nix/store/nwjx03jf33pb5lg
y9bcsqv717wxfbvsk-stm-conduit-2.7.0/lib/ghc-8.0.0.20160204/stm-conduit-2.7.0 --enable-split-obj
s --disable-library-profiling --disable-profiling --enable-shared --enable-library-vanilla --en
able-executable-dynamic --disable-tests
Configuring stm-conduit-2.7.0...
Dependency async -any: using async-2.1.0
Dependency base -any: using base-4.9.0.0
Dependency cereal -any: using cereal-0.5.1.0
Dependency cereal-conduit -any: using cereal-conduit-0.7.2.5
Dependency conduit -any: using conduit-1.2.6.2
Dependency conduit-combinators -any: using conduit-combinators-1.0.3.1
Dependency conduit-extra -any: using conduit-extra-1.1.10.1
Dependency directory -any: using directory-1.2.5.0
Dependency ghc-prim -any: using ghc-prim-0.5.0.0
Dependency lifted-async -any: using lifted-async-0.8.0.1
Dependency lifted-base -any: using lifted-base-0.2.3.6
Dependency monad-control -any: using monad-control-1.0.0.5
Dependency monad-loops -any: using monad-loops-0.4.3
Dependency resourcet -any: using resourcet-1.1.7.2
Dependency stm -any: using stm-2.4.4.1
Dependency stm-chans -any: using stm-chans-3.0.0.4
Dependency transformers -any: using transformers-0.5.1.0
Dependency void -any: using void-0.7.1
Using Cabal-1.23.1.0 compiled by ghc-8.0
Using compiler: ghc-8.0.0.20160204
Using install prefix:
/nix/store/nwjx03jf33pb5lgy9bcsqv717wxfbvsk-stm-conduit-2.7.0
Binaries installed in:
/nix/store/nwjx03jf33pb5lgy9bcsqv717wxfbvsk-stm-conduit-2.7.0/bin
Libraries installed in:
/nix/store/nwjx03jf33pb5lgy9bcsqv717wxfbvsk-stm-conduit-2.7.0/lib/ghc-8.0.0.20160204/stm-condui
t-2.7.0
Private binaries installed in:
/nix/store/nwjx03jf33pb5lgy9bcsqv717wxfbvsk-stm-conduit-2.7.0/libexec
Data files installed in:
/nix/store/nwjx03jf33pb5lgy9bcsqv717wxfbvsk-stm-conduit-2.7.0/share/x86_64-linux-ghc-8.0.0.2016
0204/stm-conduit-2.7.0
Documentation installed in:
/nix/store/nwjx03jf33pb5lgy9bcsqv717wxfbvsk-stm-conduit-2.7.0/share/doc/x86_64-linux-ghc-8.0.0.
20160204/stm-conduit-2.7.0
Configuration files installed in:
/nix/store/nwjx03jf33pb5lgy9bcsqv717wxfbvsk-stm-conduit-2.7.0/etc
No alex found
Using ar found on system at:
/nix/store/f9aj81zi2wam2dmnc30jhlr2lkwvgp49-binutils-2.23.1-dev/bin/ar
No c2hs found
No cpphs found
Using gcc version 4.9.3 given by user at:
/nix/store/2j5gi3bwsrpyfacivc28rlgiak2mdbxg-gcc-wrapper-4.9.3/bin/gcc
Using ghc version 8.0.0.20160204 found on system at:
/nix/store/9ycqyik6sknsicdjhawn49yxv7m93mnc-ghc-8.0.0.20160204/bin/ghc
Using ghc-pkg version 8.0.0.20160204 found on system at:
/nix/store/9ycqyik6sknsicdjhawn49yxv7m93mnc-ghc-8.0.0.20160204/bin/ghc-pkg
No ghcjs found
No ghcjs-pkg found
No greencard found
Using haddock version 2.17.0 found on system at:
/nix/store/9ycqyik6sknsicdjhawn49yxv7m93mnc-ghc-8.0.0.20160204/bin/haddock
No happy found
Using haskell-suite found on system at: haskell-suite-dummy-location
Using haskell-suite-pkg found on system at: haskell-suite-pkg-dummy-location
No hmake found
Using hpc version 0.67 found on system at:
/nix/store/9ycqyik6sknsicdjhawn49yxv7m93mnc-ghc-8.0.0.20160204/bin/hpc
Using hsc2hs version 0.67 found on system at:
/nix/store/9ycqyik6sknsicdjhawn49yxv7m93mnc-ghc-8.0.0.20160204/bin/hsc2hs
Using hscolour version 1.24 found on system at:
/nix/store/yrj2if1z9k739b92n4la852nvzlkz1h2-hscolour-1.24/bin/HsColour
No jhc found
Using ld found on system at:
/nix/store/2j5gi3bwsrpyfacivc28rlgiak2mdbxg-gcc-wrapper-4.9.3/bin/ld
No lhc found
No lhc-pkg found
No pkg-config found
Using strip version 2.23 found on system at:
/nix/store/f9aj81zi2wam2dmnc30jhlr2lkwvgp49-binutils-2.23.1-dev/bin/strip
Using tar found on system at:
/nix/store/hmfmqrjv73f201z9al1sgsbzkih39cvj-gnutar-1.28/bin/tar
No uhc found
building
Building stm-conduit-2.7.0...
Preprocessing library stm-conduit-2.7.0...
[1 of 5] Compiling Data.Conduit.TQueue ( Data/Conduit/TQueue.hs, dist/build/Data/Conduit/TQueue.o )
[2 of 5] Compiling Data.Conduit.TMChan ( Data/Conduit/TMChan.hs, dist/build/Data/Conduit/TMChan.o )
[3 of 5] Compiling Data.Conduit.Utils ( Data/Conduit/Utils.hs, dist/build/Data/Conduit/Utils.o )
[4 of 5] Compiling Data.Conduit.Async.Composition ( Data/Conduit/Async/Composition.hs, dist/build/Data/Conduit/Async/Composition.o )
Data/Conduit/Async/Composition.hs:207:42: error:
Not in scope: type constructor or class ‘Constraint’
builder for ‘/nix/store/jyz1m745y8nhxk7l2h05c2p2arihq42p-stm-conduit-2.7.0.drv’ failed with exit code 1
error: build of ‘/nix/store/jyz1m745y8nhxk7l2h05c2p2arihq42p-stm-conduit-2.7.0.drv’ failed
The current type of (>=<)
and mergeSources
requires the Source
s being merged to use a monad of the form ResourceT m
for some m
. For example:
(>=<) :: (MonadIO m, MonadBaseControl IO m) => Source (ResourceT m) a -> Source (ResourceT m) a -> ResourceT m (Source (ResourceT m) a)
If possible, it would be great if this signature could be relaxed to a type like this one:
(>=<) :: (MonadIO m, MonadBaseControl IO m, MonadResource m) => Source m a -> Source m a -> ResourceT m (Source m a)
There may be some reason why this can't work, in which case I apologize for raising the issue. It does seem that it was once this way until version 0.4, so perhaps it was discovered to be unworkable.
If it is unworkable, you are aware of a workaround, and have time to explain it briefly that would be awesome. Thanks for the great library.
As far as I can see the stm-conduit-3.0.0 was designed with conduit < 1.3. conduit-combinators was a separate package prior to conduit-1.3. At some point, it was marked as deprecated and all of its content was purged (in fact merged to conduit-1.3). That "purged" version is uploaded to hackage and marked as conduit-combinators-1.3.0.
Now, if we take stm-conduit-3.0.0 and try to build it, cabal-install will take conduit<1.3 but conduit-combinators-1.3 which would result in effective absence of the body of the conduit-combinators. Given that, stm-conduit does not compile with what is in hackage today:
gzh@vmdeb9:~/tmp$ cabal sandbox init Writing a default package environment file to /home/gzh/tmp/cabal.sandbox.config Creating a new sandbox at /home/gzh/tmp/.cabal-sandbox gzh@vmdeb9:~/tmp$ cabal install stm-conduit-3.0.0 Resolving dependencies... Notice: installing into a sandbox located at /home/gzh/tmp/.cabal-sandbox Configuring cereal-0.5.5.0... Configuring conduit-combinators-1.3.0... Configuring integer-logarithms-1.0.2.1... Configuring mtl-2.2.2... Configuring primitive-0.6.4.0... Configuring random-1.1... Configuring semigroups-0.18.5... Configuring unliftio-core-0.1.1.0... Configuring void-0.7.2... Configuring monad-loops-0.4.3... Configuring base-orphans-0.8... Configuring stm-2.4.5.0... Configuring zlib-0.6.2... Configuring transformers-compat-0.6.2... Configuring text-1.2.3.0... Configuring network-2.7.0.1... Building cereal-0.5.5.0... Building mtl-2.2.2... Building conduit-combinators-1.3.0... Building integer-logarithms-1.0.2.1... Building random-1.1... Building semigroups-0.18.5... Building unliftio-core-0.1.1.0... Building monad-loops-0.4.3... Building base-orphans-0.8... Building stm-2.4.5.0... Building void-0.7.2... Building primitive-0.6.4.0... Building zlib-0.6.2... Building text-1.2.3.0... Building transformers-compat-0.6.2... Installed void-0.7.2 Installed conduit-combinators-1.3.0 Installed semigroups-0.18.5 Installed unliftio-core-0.1.1.0 Installed monad-loops-0.4.3 Installed integer-logarithms-1.0.2.1 Installed stm-2.4.5.0 Configuring stm-chans-3.0.0.4... Installed base-orphans-0.8 Building network-2.7.0.1... Installed mtl-2.2.2 Installed transformers-compat-0.6.2 Configuring transformers-base-0.4.5.2... Configuring mmorph-1.1.2... Configuring exceptions-0.10.0... Building stm-chans-3.0.0.4... Building exceptions-0.10.0... Building transformers-base-0.4.5.2... Building mmorph-1.1.2... Installed transformers-base-0.4.5.2 Configuring monad-control-1.0.2.3... Installed mmorph-1.1.2 Building monad-control-1.0.2.3... Installed stm-chans-3.0.0.4 Installed random-1.1 Installed monad-control-1.0.2.3 Configuring lifted-base-0.2.3.12... Installed exceptions-0.10.0 Installed zlib-0.6.2 Building lifted-base-0.2.3.12... Installed lifted-base-0.2.3.12 Configuring resourcet-1.1.11... Building resourcet-1.1.11... Installed network-2.7.0.1 Installed resourcet-1.1.11 Installed primitive-0.6.4.0 Configuring conduit-1.2.13.1... Building conduit-1.2.13.1... Installed cereal-0.5.5.0 Installed conduit-1.2.13.1 Configuring cereal-conduit-0.7.3... Building cereal-conduit-0.7.3... Installed cereal-conduit-0.7.3 Installed text-1.2.3.0 Configuring hashable-1.2.7.0... Configuring blaze-builder-0.4.1.0... Building hashable-1.2.7.0... Building blaze-builder-0.4.1.0... Installed hashable-1.2.7.0 Configuring constraints-0.10.1... Configuring async-2.2.1... Configuring scientific-0.3.6.2... Building constraints-0.10.1... Building scientific-0.3.6.2... Building async-2.2.1... Installed blaze-builder-0.4.1.0 Installed async-2.2.1 Configuring typed-process-0.2.2.0... Configuring streaming-commons-0.1.19... Building typed-process-0.2.2.0... Building streaming-commons-0.1.19... Installed constraints-0.10.1 Configuring lifted-async-0.10.0.2... Installed typed-process-0.2.2.0 Building lifted-async-0.10.0.2... Installed scientific-0.3.6.2 Configuring attoparsec-0.13.2.2... Building attoparsec-0.13.2.2... Installed lifted-async-0.10.0.2 Installed streaming-commons-0.1.19 Installed attoparsec-0.13.2.2 Configuring conduit-extra-1.2.3.2... Building conduit-extra-1.2.3.2... Installed conduit-extra-1.2.3.2 Configuring stm-conduit-3.0.0... Building stm-conduit-3.0.0... Failed to install stm-conduit-3.0.0 Build log ( /home/gzh/tmp/.cabal-sandbox/logs/ghc-8.2.1/stm-conduit-3.0.0-JeGUQQcB8GpJmnDKT0Dhgk.log ): cabal: Entering directory '/tmp/cabal-tmp-105076/stm-conduit-3.0.0' Configuring stm-conduit-3.0.0... Preprocessing library for stm-conduit-3.0.0.. Building library for stm-conduit-3.0.0.. [1 of 5] Compiling Data.Conduit.Async.Composition ( Data/Conduit/Async/Composition.hs, dist/dist-sandbox-9c730035/build/Data/Conduit/Async/Composition.o )Data/Conduit/Async/Composition.hs:30:1: error:
Could not find module `Conduit'
Use -v to see a list of the files searched for.
|
30 | import Conduit
| ^^^^^^^^^^^^^^
cabal: Leaving directory '/tmp/cabal-tmp-105076/stm-conduit-3.0.0'
cabal: Error: some packages failed to install:
stm-conduit-3.0.0-JeGUQQcB8GpJmnDKT0Dhgk failed during the building phase. The
exception was:
ExitFailure 1
I've got an obvious fix here https://github.com/gzh/stm-conduit/commit/9b47430cac65b2e47cdb19f9c00fd550bc9d5bd6
but cannot do a pull request because there's no 3.0.0 branch in your repository. That commit should be applied to commit aaba396, which looks like the latest 3.0.0 actually compatible with conduit < 1.3.
Do you think it's possible to upload a 3.0.0 revision 2 to hackage?
The version of this package that is released on Hackage is 2.5.2. The cabal file on Hackage points to this repository. But the version in the cabal file of this repository is 2.5.1.
Current implementation of mergeSources
is not exception safe. If an asynchronous exception will arrive, or if source will be explicitly closed, then all forked processes will not be closed. This means that there will be dangling processes running.
Hi,
I discovered a deadlock in the use of the $$& operator. Here is the code snippet to reproduce the deadlock:
C.sourceList [1..100] $$& C.fold (+) 0
*** Exception: thread blocked indefinitely in an STM transaction
I wrote a test which reproduces the bug:
svenkeidel/stm-conduit@e649c4693920b29fe2c9b1693da711b61ded8138
May I help you with fixing this bug?
Best Sven
I've yet to successfully use gatherFrom
, possibly for various reasons, but one may be that yield
takes place in a line that seems to never be used (i.e. the value is discarded):
stm-conduit/Data/Conduit/Async.hs
Line 44 in f8710fc
At first glance I assumed mergeSources
would concurrently produce values from the provided Source
s and provide a single Source
from which these can be read.
In essence this create a single Source
which internally was concurrently generating the values to pass downstream.
I then assumed that mergeConduits
would return a Conduit
which would:
Accept inputs from upstream
Distribute the inputs across the provided Conduit
s for concurrent processing
Join the output of the provided Conduit
s into a single output stream.
In essence I assumed this would be creating a single Conduit
that internally processed values concurrently.
After reading the code and playing around with this a bit it seems that the returned Conduit
never await
s values from upstream, it only pulls values from the internally managed TBMChan
. Considering this, it's not really returning a Conduit
, it's actually a Source
.
I don't think this was the intended behavior of this function based on it's test. For instance, if you edit test_mergeConduits
to input (and expect) [1..20]
instead of [1..10]
you'll see it fails with
ERROR: thread blocked indefinitely in an STM transaction
The only reason the test currently passes is because the internal TBMChan
is large enough to hold the entirety of the upstream values.
Is this a bug?
Should the the returned Conduit
from mergeConduits
behave as I expected?
the functionality has been merged in conduit and the two packages are incompatible now
Is there a way to have mergeSources terminate after one of the sources has terminated? I can show you a code sample if need be. Basically, my use case is that I've made a source out of a Postgres trigger/notify thread, and a source that is is the appSource for a tcp server, and merged them. When the appSource terminates, the trigger thread sticks around - which is a file descriptor leak.
I could likely roll something with e.g. STM to make the trigger thread stop but I thought you might have done it already given how mergeSources is implemented.
I think it'd be rather cool if this used runConduit
directly when the buffer count is 0. This is handy when you want to use some stm-conduit code as a building block where some use-cases benefit from buffering while others do not.
It's not a big deal - quite straightforward to check if the buffer count is 0 and do this manually. But figured I may as well mention it anyway.
Currently, if I write my own operator alias for buffer
with a different buffer size, I cannot give it a polymorphic type signature, as the CCatable
class isn't exported.
(.|&) = STMConduit.buffer ...
is going to monomorphize to either Conduit
or CConduit
, which means I can't use it for eg Data.Conduit.List.mapM
.
I am having an issue with using bracketP
/ResourceT
with mergeSources
:
mergeSources
to join two or more conduit sources which are reading from different queues but are sharing the same connectionThe easiest way to reproduce it is to add =$= take 1
to the result stream after mergeSources
. After the 1st element is consumed by the sink the pipe is exhausted and the resource finaliser is called. The exception of accessing the closed resource follows.
Is it a bug or what would be the proper way to terminate "merged" sources?
I've made an attempt at generalizing Data.Conduit.Async
to allow for more than one concurrency join point, in order to allow code that looks like
fromNetwork $$& (process &= process &= process) $=& toNetwork
or
fromNetwork $$& (process &= process &= process) `buf` toNetwork
where buf = bufferToFile' 1000 Nothing "/tmp"
I may have gone a little overboard in the type magic to overload $$&
and $=&
this way, but at least code using it looks nice and it should be source-compatible with almost all existing stm-conduit user code. If you're interested, I can clean this up into a proper pull request, as right now it's a completely separate project that I didn't realize would become this exactly when I started.
Error: setup: Encountered missing or private dependencies:
transformers >=0.2 && <0.6
It seems that stm-conduit
fell out of stackage nightly: https://github.com/fpco/stackage/blob/master/build-constraints.yaml It would be nice to have it back in.
I'm seeing this starting with 2.6.0:
Building stm-conduit-2.6.0...
Preprocessing library stm-conduit-2.6.0...
[1 of 5] Compiling Data.Conduit.TQueue ( Data/Conduit/TQueue.hs, dist/build/Data/Conduit/TQueue.o )
[2 of 5] Compiling Data.Conduit.TMChan ( Data/Conduit/TMChan.hs, dist/build/Data/Conduit/TMChan.o )
[3 of 5] Compiling Data.Conduit.Utils ( Data/Conduit/Utils.hs, dist/build/Data/Conduit/Utils.o )
[4 of 5] Compiling Data.Conduit.Async.Composition ( Data/Conduit/Async/Composition.hs, dist/build/Data/Conduit/Async/Composition.o )
[5 of 5] Compiling Data.Conduit.Async ( Data/Conduit/Async.hs, dist/build/Data/Conduit/Async.o )
In-place registering stm-conduit-2.6.0...
Preprocessing test suite 'stm-conduit-doctests' for stm-conduit-2.6.0...
Test/DocTest.hs:1:8:
File name does not match module name:
Saw: ‘Main’
Expected: ‘Test.DocTest’
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.