Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Haskell data marshaling layer. Uses type level equations to optimize buffering.
branch: master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.



A (in development) high performance data marshaling layer for haskell. Uses a pair of parameterized
monads to represent: Data marshalling actions with static buffering requirements (EG: Needs no more
than 100 bytes available to succeed) ; Data marshalling actions with a dynamic composition of
actions with static buffering requirements.

Currently bind-marshal can only be used via dev-system. A build/run/test dev tool I have not
currently released. Sorry!

The static buffering actions parameterize a monad with the maximum number of bytes that will either
be read/written from/to a buffer. A type level number is used to represent the maximum number of

For example, this expression represents a serialization action that writes at most 8 bytes in host
endian order:

foo :: StaticSerAction D8 () -- D8 is the type level representation of 8
foo = do
    ser (256 :: Word32) -- ser for serialize
    ser (13 :: Word32)
    return ()

A more complex example would be:
bar :: StaticSerAction D16 ()
bar = do
    _ <- foo
    _ <- foo
    return ()

Static actions are useful for basic structures. However, most structures contain components whose
marshalled size are dynamic; Not known at compile time. 

Bind-marshal represents these cases with the the Dynamic actions: DynamicSerAction,
DynamicDesAction. Which are actions composed of individual static actions. Where before each static
action is a check that assures the buffer satisfies the requirements of the static action. 

For example, the following action:

pew i = do 
    replicateM i $ dyn_action $ do      
        x :: Word32 <- des              
        y :: Word32 <- des              
        return ()

Is evaluated (more or less) like so:
    0. For i times
        a. Verify there is at least 8 bytes available to read
        b. Read 4 bytes
        c. Read 4 bytes

Currently a "dyn_action" is required to "lift" a static action into a dynamic action monad. This
should be automatic, but I have thus failed to get automatic lifting to work as a user expects. So
the user has to manually insert dyn_action when needed. However, if the dyn_action is ommited the
equation will fail to type check. 

Handling of failures is done incorrectly right now. The static memory actions have a failure
continuation. The dynamic memory actions do not have a failure continuation: Any failure results in
an IO exception. For a smooth implementation of an interface like Control.Applicative.Alternative 
all failures should be propogated via a failure continuation. 

Consistently using a failure continuation for error popogation does not resolve all issues with
error handling. A pattern match failure followed by a "return _ :: Identity _" will use the fail
equation for Identity (Prelude.error). This may not be what the user expects. So IO exception will
still need to be handled and forwarded to the failure continuation when appropriate.

Something went wrong with that request. Please try again.