ekmett / bytes Goto Github PK
View Code? Open in Web Editor NEWSerialization primitives that work with both cereal and binary.
Home Page: http://hackage.haskell.org/package/bytes
License: Other
Serialization primitives that work with both cereal and binary.
Home Page: http://hackage.haskell.org/package/bytes
License: Other
Version >= 0.6 lack both uncheckedSkip and lookAheadE.
When running cabal build, I get the following errors:
src/Data/Bytes/Put.hs:32:1: error:
Failed to load interface for ‘Control.Monad.Reader’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Put.hs:34:1: error:
Failed to load interface for ‘Control.Monad.RWS.Lazy’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Put.hs:35:1: error:
Failed to load interface for ‘Control.Monad.RWS.Strict’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Put.hs:36:1: error:
Failed to load interface for ‘Control.Monad.State.Lazy’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Put.hs:37:1: error:
Failed to load interface for ‘Control.Monad.State.Strict’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Put.hs:38:1: error:
Failed to load interface for ‘Control.Monad.Writer.Lazy’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Put.hs:39:1: error:
Failed to load interface for ‘Control.Monad.Writer.Strict’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
[4 of 5] Compiling Data.Bytes.Get ( src/Data/Bytes/Get.hs, dist/build/Data/Bytes/Get.p_o )
src/Data/Bytes/Get.hs:31:1: error:
Failed to load interface for ‘Control.Monad.Reader’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Get.hs:33:1: error:
Failed to load interface for ‘Control.Monad.RWS.Lazy’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Get.hs:34:1: error:
Failed to load interface for ‘Control.Monad.RWS.Strict’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Get.hs:35:1: error:
Failed to load interface for ‘Control.Monad.State.Lazy’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Get.hs:36:1: error:
Failed to load interface for ‘Control.Monad.State.Strict’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Get.hs:37:1: error:
Failed to load interface for ‘Control.Monad.Writer.Lazy’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
src/Data/Bytes/Get.hs:38:1: error:
Failed to load interface for ‘Control.Monad.Writer.Strict’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1’?
Use -v to see a list of the files searched for.
I originally got this when trying to add the Linear library to my project:
cabal install Linear
Note: I'm pretty new to haskell and cabal so let me know if I left any valuable info out.
Before I found out about this library I had implemented transformers over Get
and Put
of cereal
library. What about merging something in the spirit of this into bytes
?
Currently, bytes
defines functions to convert from floating-point values to word values (and vice versa) in i2d.c
. However, in base-4.10.0.0
(GHC 8.2) and later, the GHC.Float
module offers equivalent functionality in the castDoubleToWord64
function, as well as its cohorts. As far as I can tell, these functions are bit-for-bit compatible, although I'd have to stare at the corresponding Cmm code to know for sure.
If we used the GHC.Float
functions instead, we would no longer need to link against C code on recent versions of GHC. This has come up elsewhere in ekmett/bits#7 (comment).
There are issues with this library and the default encoding of negative Integer
.
Encoding with the cereal
library:
λ :m + Data.Serialize Data.ByteString.Base16
λ let bs = encode (-1 :: Integer)
λ encodeBase16 bs
"00ffffffff"
λ decode bs :: Either String Integer
Right (-1)
Encoding with the bytes
library:
λ let bs = runPutS $ serialize (-1 :: Integer)
λ encodeBase16 bs
"ff"
λ runGetS deserialize bs :: Either String Integer
Left "too few bytes\nFrom:\tdemandInput\n\n"
λ let bl = runPutL $ serialize (-1 :: Integer)
λ Data.ByteString.Lazy.Base16.encodeBase16 bl
"ff"
λ runGetL deserialize bl :: Integer
*** Exception: Data.Binary.Get.runGet at position 1: not enough bytes
CallStack (from HasCallStack):
error, called at libraries/binary/src/Data/Binary/Get.hs:351:5 in binary-0.8.8.0:Data.Binary.Get
Running on OS X 10.10.3.
$ cabal --version
cabal-install version 1.16.0.2
using version 1.16.0 of the Cabal library
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.8.4
$ cabal install bytes
Resolving dependencies...
[1 of 1] Compiling Main ( /var/folders/vv/jwv8z8yj66z1rytjgnsn8l1c0000gn/T/bytes-0.15-15766/bytes-0.15/Setup.lhs, /var/folders/vv/jwv8z8yj66z1rytjgnsn8l1c0000gn/T/bytes-0.15-15766/bytes-0.15/dist/setup/Main.o )
Linking /var/folders/vv/jwv8z8yj66z1rytjgnsn8l1c0000gn/T/bytes-0.15-15766/bytes-0.15/dist/setup/setup ...
Configuring bytes-0.15...
Building bytes-0.15...
Preprocessing library bytes-0.15...
[1 of 5] Compiling Data.Bytes.Signed ( src/Data/Bytes/Signed.hs, dist/build/Data/Bytes/Signed.o )
[2 of 5] Compiling Data.Bytes.VarInt ( src/Data/Bytes/VarInt.hs, dist/build/Data/Bytes/VarInt.o )
[3 of 5] Compiling Data.Bytes.Put ( src/Data/Bytes/Put.hs, dist/build/Data/Bytes/Put.o )
[4 of 5] Compiling Data.Bytes.Get ( src/Data/Bytes/Get.hs, dist/build/Data/Bytes/Get.o )
[5 of 5] Compiling Data.Bytes.Serial ( src/Data/Bytes/Serial.hs, dist/build/Data/Bytes/Serial.o )
ld: library not found for -lHSvoid-0.7-ghc7.8.4
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Failed to install bytes-0.15
cabal: Error: some packages failed to install:
bytes-0.15 failed during the building phase. The exception was:
ExitFailure 1
$
It looks like the most recent release on Hackage (1.15.5) has time>=1.2 && <1.9
.
Hi, I'm trying to install random-fu-0.2.7.0 with ghc v8.2.1 and cabal 1.22.5.0, in order to access random numbers with modern Haskell Platform. However, when I try to install random-fu, cabal responds with an error about the bytes package:
$ shake
...
Command: cabal install --bindir dist/bin
Exit code: 1
Stderr:
cabal: Error: some packages failed to install:
bytes-0.15.3 failed during the configure step. The exception was:
user error ('/usr/local/bin/ghc' exited with an error:
/var/folders/53/300vy1ys7tv8h8fr_z3tm8gr0000gn/T/cabal-tmp-8690/bytes-0.15.3/dist/setup/setup.hs:168:18:
error:
• Couldn't match type ‘Distribution.Types.MungedPackageId.MungedPackageId’
with ‘Distribution.Types.PackageId.PackageIdentifier’
Expected type: [(UnitId, PackageId)]
Actual type: [(UnitId,
Distribution.Types.MungedPackageId.MungedPackageId)]
• In the expression:
nub $ componentPackageDeps xs ++ componentPackageDeps ys
In an equation for ‘testDeps’:
testDeps xs ys
= nub $ componentPackageDeps xs ++ componentPackageDeps ys
|
168 | testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps
ys
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
genetics-0.0.3 depends on bytes-0.15.3 which failed to install.
log-domain-0.12 depends on bytes-0.15.3 which failed to install.
random-fu-0.2.7.0 depends on bytes-0.15.3 which failed to install.
)
Could the bytes package be updated to reflect changes in the GHC 7 and GHC 8 API?
As a workaround, I am using the random package instead.
There are serialization libraries, which provide support for a wider range of types, e.g.: Integer, Ordering, Month, Day, ClockTime, CalendarTime, TimeDiff, AbsoluteTime, LocalTime, ZonedTime, TimeOfDay, TimeZone, UTCTime, NominalDiffTime, Day, UniversalTime, DiffTime.
The implementation of those for "bytes" should be painless, as we can simply use the code from here as a reference.
The fact that instances for those quite standard types are missing from the library introduces the notorious "Orphan instances" issue, if they get implemented in whatever outer library.
If I get a confirmation on this, I can post an appropriate pull request.
bytes
fails to build with GHC 8.8.1-alpha1:
[5 of 5] Compiling Data.Bytes.Serial ( src/Data/Bytes/Serial.hs, /home/rgscott/Documents/Hacking/Haskell/staging/dist-newstyle/build/x86_64-linux/ghc-8.8.0.20190424/bytes-0.15.5/build/Data/Bytes/Serial.o )
src/Data/Bytes/Serial.hs:282:28: error:
• Could not deduce (MonadFail m) arising from a use of ‘fail’
from the context: (MonadGet m, Storable a)
bound by the type signature for:
restore :: forall (m :: * -> *) a. (MonadGet m, Storable a) => m a
at src/Data/Bytes/Serial.hs:278:1-54
Possible fix:
add (MonadFail m) to the context of
the type signature for:
restore :: forall (m :: * -> *) a. (MonadGet m, Storable a) => m a
• In the second argument of ‘($)’, namely
‘fail "restore: Required more bytes"’
In a stmt of a 'do' block:
unless (n >= required) $ fail "restore: Required more bytes"
In the expression:
do let required = sizeOf (undefined :: a)
PS fp o n <- getByteString required
unless (n >= required) $ fail "restore: Required more bytes"
return
$ unsafePerformIO $ withForeignPtr fp $ \ p -> peekByteOff p o
|
282 | unless (n >= required) $ fail "restore: Required more bytes"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/Data/Bytes/Serial.hs:345:17: error:
• Could not deduce (MonadFail m) arising from a use of ‘fail’
from the context: MonadGet m
bound by the type signature for:
deserialize :: forall (m :: * -> *). MonadGet m => m Void
at src/Data/Bytes/Serial.hs:345:3-13
Possible fix:
add (MonadFail m) to the context of
the type signature for:
deserialize :: forall (m :: * -> *). MonadGet m => m Void
• In the expression: fail "I looked into the void."
In an equation for ‘deserialize’:
deserialize = fail "I looked into the void."
In the instance declaration for ‘Serial Void’
|
345 | deserialize = fail "I looked into the void."
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/Data/Bytes/Serial.hs:608:18: error:
• Could not deduce (MonadFail m) arising from a use of ‘fail’
from the context: MonadGet m
bound by the type signature for:
gdeserialize :: forall (m :: * -> *) a. MonadGet m => m (V1 a)
at src/Data/Bytes/Serial.hs:608:3-14
Possible fix:
add (MonadFail m) to the context of
the type signature for:
gdeserialize :: forall (m :: * -> *) a. MonadGet m => m (V1 a)
• In the expression: fail "I looked into the void."
In an equation for ‘gdeserialize’:
gdeserialize = fail "I looked into the void."
In the instance declaration for ‘GSerial V1’
|
608 | gdeserialize = fail "I looked into the void."
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/Data/Bytes/Serial.hs:622:10: error:
• Could not deduce (MonadFail m) arising from a use of ‘fail’
from the context: (GSerial f, GSerial g)
bound by the instance declaration
at src/Data/Bytes/Serial.hs:616:10-52
or from: MonadGet m
bound by the type signature for:
gdeserialize :: forall (m :: * -> *) a.
MonadGet m =>
m ((:+:) f g a)
at src/Data/Bytes/Serial.hs:619:3-14
Possible fix:
add (MonadFail m) to the context of
the type signature for:
gdeserialize :: forall (m :: * -> *) a.
MonadGet m =>
m ((:+:) f g a)
• In the expression: fail "Missing case"
In a case alternative: _ -> fail "Missing case"
In the expression:
case a of
0 -> liftM L1 gdeserialize
1 -> liftM R1 gdeserialize
_ -> fail "Missing case"
|
622 | _ -> fail "Missing case"
| ^^^^^^^^^^^^^^^^^^^
src/Data/Bytes/Serial.hs:791:24: error:
• Could not deduce (MonadFail m) arising from a use of ‘fail’
from the context: MonadGet m
bound by the type signature for:
gdeserializeWith :: forall (m :: * -> *) a.
MonadGet m =>
m a -> m (V1 a)
at src/Data/Bytes/Serial.hs:791:3-18
Possible fix:
add (MonadFail m) to the context of
the type signature for:
gdeserializeWith :: forall (m :: * -> *) a.
MonadGet m =>
m a -> m (V1 a)
• In the expression: fail "I looked into the void."
In an equation for ‘gdeserializeWith’:
gdeserializeWith _ = fail "I looked into the void."
In the instance declaration for ‘GSerial1 V1’
|
791 | gdeserializeWith _ = fail "I looked into the void."
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/Data/Bytes/Serial.hs:803:10: error:
• Could not deduce (MonadFail m) arising from a use of ‘fail’
from the context: (GSerial1 f, GSerial1 g)
bound by the instance declaration
at src/Data/Bytes/Serial.hs:797:10-55
or from: MonadGet m
bound by the type signature for:
gdeserializeWith :: forall (m :: * -> *) a.
MonadGet m =>
m a -> m ((:+:) f g a)
at src/Data/Bytes/Serial.hs:800:3-18
Possible fix:
add (MonadFail m) to the context of
the type signature for:
gdeserializeWith :: forall (m :: * -> *) a.
MonadGet m =>
m a -> m ((:+:) f g a)
• In the expression: fail "Missing case"
In a case alternative: _ -> fail "Missing case"
In the expression:
case a of
0 -> liftM L1 (gdeserializeWith m)
1 -> liftM R1 (gdeserializeWith m)
_ -> fail "Missing case"
|
803 | _ -> fail "Missing case"
| ^^^^^^^^^^^^^^^^^^^
src/Data/Bytes/Serial.hs:839:10: error:
• Could not deduce (MonadFail m) arising from a use of ‘fail’
from the context: MonadGet m
bound by the type signature for:
deserializeWith2 :: forall (m :: * -> *) a b.
MonadGet m =>
m a -> m b -> m (Either a b)
at src/Data/Bytes/Serial.hs:836:3-18
Possible fix:
add (MonadFail m) to the context of
the type signature for:
deserializeWith2 :: forall (m :: * -> *) a b.
MonadGet m =>
m a -> m b -> m (Either a b)
• In the expression: fail "Missing case"
In a case alternative: _ -> fail "Missing case"
In the expression:
case a of
0 -> liftM Left m
1 -> liftM Right n
_ -> fail "Missing case"
|
839 | _ -> fail "Missing case"
| ^^^^^^^^^^^^^^^^^^^
All of these errors occur within a MonadGet
constraint, so one tempting solution to this problem is to simply make MonadFail
a superclass of MonadGet
:
diff --git a/bytes.cabal b/bytes.cabal
index 401777b..540c928 100644
--- a/bytes.cabal
+++ b/bytes.cabal
@@ -74,7 +74,8 @@ library
build-depends: ghc-prim
if impl(ghc < 8.0)
- build-depends: semigroups >= 0.5 && < 1
+ build-depends: fail == 4.9.*,
+ semigroups >= 0.5 && < 1
exposed-modules:
Data.Bytes.Get
diff --git a/src/Data/Bytes/Get.hs b/src/Data/Bytes/Get.hs
index 6ab1a04..fd5e26b 100644
--- a/src/Data/Bytes/Get.hs
+++ b/src/Data/Bytes/Get.hs
@@ -28,6 +28,7 @@ module Data.Bytes.Get
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif
+import qualified Control.Monad.Fail as Fail
import Control.Monad.Reader
import Control.Monad.Trans.Except as Except
import Control.Monad.RWS.Lazy as Lazy
@@ -43,7 +44,7 @@ import Data.Int
import qualified Data.Serialize.Get as S
import Data.Word
-class (Integral (Remaining m), Monad m, Applicative m) => MonadGet m where
+class (Integral (Remaining m), Fail.MonadFail m, Applicative m) => MonadGet m where
-- | An 'Integral' number type used for unchecked skips and counting.
type Remaining m :: *
This makes bytes
build on recent GHCs. For older (pre-8.0) GHCs, however, this presents a problem. Here's what happens if you build with GHC 7.10.3, for instance:
[4 of 5] Compiling Data.Bytes.Get ( src/Data/Bytes/Get.hs, /home/rgscott/Documents/Hacking/Haskell/staging/bytes/dist-newstyle/build/x86_64-linux/ghc-7.10.3/bytes-0.15.5/build/Data/Bytes/Get.o )
src/Data/Bytes/Get.hs:202:10:
No instance for (Fail.MonadFail B.Get)
arising from the superclasses of an instance declaration
In the instance declaration for ‘MonadGet B.Get’
Eek! Get
from the binary
package has only been an instance of MonadFail
since 0.8.2.0
, which is more recent than the version that is shipped with GHC 7.10.3.
One alternative woud be to switch all uses of fail
with error
. But this feels a bit wrong, since most parser data types have dedicated fail
implementations that do something besides throw an exception.
... which is bundled with GHC-9.4
I didn't check whether there's somethign else to do, but I hope that adding GHC-9.4 CI job will tell that.
I rolled the expression problem dice and decided this was the better repo to open the issue in :).
Something that is nice about having MonadGet
and MonadPut
as classes is you can use the same serialization logic for different purposes. For instance, you can create a MonadPut
instance based on a cryptographic hash accumulator, and now your serialization code for your type doubles for creating hashes. Maybe a bit ad hoc, but it works great!
Here are a couple other ideas for instances:
MonadPut
and MonadGet
. So you write and read from it as normal, but it's doing incremental compression and decompression. Perhaps you can get the same thing serializing to a lazy bytestring, then compressing that, but it's probably faster to just have the instances do this directly.MonadPut
and MonadGet
. Again, you read and write as normal, but it's encrypting / decrypting as you go.Not sure if you'd want include any of these in this package, but just wanted to get your thoughts. Maybe such instances belong in a separate package that depends on bytes?
Noticed this while fixing up cabal meta-data:
For GHC 7.0:
src/Data/Bytes/Get.hs:4:14:
Unsupported extension: DefaultSignatures
cabal: Error: some packages failed to install:
bytes-0.14.1.3 failed during the building phase.
and for GHC 7.2.2:
src/Data/Bytes/Serial.hs:90:8:
Could not find module `GHC.Generics'
It is a member of the hidden package `ghc-prim'.
Perhaps you need to add `ghc-prim' to the build-depends in your .cabal file.
Use -v to see a list of the files searched for.
cabal: Error: some packages failed to install:
bytes-0.14.1.3 failed during the building phase.
% cabal build -w ghc-7.10.3 --constraint='bytestring >=0.11' --allow-newer=bytestring
src/Data/Bytes/Serial.hs:291:3:
Not in scope: data constructor ‘PS’
Perhaps you meant ‘BS’ (imported from Data.ByteString.Internal)
with
source-repository-package
type: git
location: https://github.com/haskell/text
tag: v1.2.4.1-rc1
CI doesn't test these. They are however easy to spot if you grep for PS
constructor.
Add descriptions for:
flag test-doctests
flag lib-Werror
e8de663 and some commits before make this library work with GHC 8.2 and Cabal 2.0, but it's not part of any release yet.
Can you make a release on hackage?
FWIW the testsuite passes with GHC 8.2.
Full error message below. tl;dr: Data.Ord doesn't provide the Down newtype wrapper.
creating dist/build/autogen
creating dist/build
creating dist/build/autogen
Component build order: library
creating dist/build
creating dist/build/autogen
Building bytes-0.14...
Preprocessing library bytes-0.14...
Building library...
'/opt/ghc-7.4.2/bin/ghc' '--info'
'/opt/ghc-7.4.2/bin/ghc' '--info'
creating dist/build
/opt/ghc-7.4.2/bin/ghc --make -fbuilding-cabal-package -O -outputdir dist/build -odir dist/build -hidir dist/build -stubdir dist/build -i -idist/build -isrc -idist/build/autogen -Idist/build/autogen -Idist/build -optP-include -optPdist/build/autogen/cabal_macros.h -package-name bytes-0.14 -hide-all-packages -no-user-package-conf -package-conf /var/lib/jenkins/workspace/Stackage with GHC 7.4.2/stackage/sandbox/package-db -package-conf dist/package.conf.inplace -package-id base-4.5.1.0-66f22db3dfcd87541c9c7e50e7095d26 -package-id binary-0.5.1.0-1dd25e339bc04e2d8ca8103c35947bf6 -package-id bytestring-0.9.2.1-503e91bb155301fdb1956cb5c26ce6e9 -package-id cereal-0.4.0.1-1776021c218430a3f5480933e945f481 -package-id containers-0.4.2.1-75f143aa39a3e77a1ce2300025bdd8ce -package-id ghc-prim-0.2.0.0-7d3c2c69a5e8257a04b2c679c40e2fa7 -package-id mtl-2.1.2-02e701f9b1590ee88a0b5b0bd5d93a29 -package-id text-0.11.3.1-41f05eb413a8fa91f09d91d3051e4ae4 -package-id time-1.4-d61e2caaa0486655b4e141dc277ed49f -package-id transformers-0.3.0.0-8e66ecc7d4dae2b07b2b5406908c70e4 -package-id transformers-compat-0.1.1.1-aa42b3b342d5fb26f3bee24e1d9fe0d3 -package-id void-0.6.1-e9a931e30ce8da0833d33dd8285bd347 -XHaskell98 Data.Bytes.Get Data.Bytes.Put Data.Bytes.Serial Data.Bytes.Signed Data.Bytes.VarInt -Wall -fwarn-tabs -O2
[1 of 5] Compiling Data.Bytes.Signed ( src/Data/Bytes/Signed.hs, dist/build/Data/Bytes/Signed.o )
[2 of 5] Compiling Data.Bytes.VarInt ( src/Data/Bytes/VarInt.hs, dist/build/Data/Bytes/VarInt.o )
[3 of 5] Compiling Data.Bytes.Put ( src/Data/Bytes/Put.hs, dist/build/Data/Bytes/Put.o )
[4 of 5] Compiling Data.Bytes.Get ( src/Data/Bytes/Get.hs, dist/build/Data/Bytes/Get.o )
[5 of 5] Compiling Data.Bytes.Serial ( src/Data/Bytes/Serial.hs, dist/build/Data/Bytes/Serial.o )
src/Data/Bytes/Serial.hs:61:18:
Module `Data.Ord' does not export `Down(..)'
The isolate
function available in both binary
and cereal
provides a very useful abstraction.
With isolate
:
isolate (fromIntegral len) $ case cmd of
MCVersion -> MVersion <$> get
MCAddr -> MAddr <$> get
_ -> fail $ "get: command " ++ show cmd ++ " should not carry a payload"
Without isolate
:
ensure (fromIntegral len) >>= \bs ->
let f = case cmd of
MCVersion -> MVersion <$> deserialize
MCAddr -> MAddr <$> deserialize
_ -> fail $ "get: command " ++ show cmd ++ " should not carry a payload"
either fail return (runGetS f bs)
Getting out of the monad to get right back into it feels clumsy.
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.