An alternative implementation of Thrift for Haskell.

Version on this page:
LTS Haskell 22.30:
Stackage Nightly 2024-07-22:
Latest on Hackage:

See all snapshots pinch appears in

BSD-3-Clause licensed by Abhinav Gupta
Maintained by [email protected]
This version can be pinned in stack with:pinch-,4150


pinch aims to provide an alternative implementation of Apache Thrift for Haskell. The pinch library itself acts only as a serialization library. Types specify their Thrift encoding by defining instances of the Pinchable typeclass, which may be done by hand or automatically with the use of Generics.

Haddock documentation for this package is avilable on Hackage and here.


Types which can be encoded into Thrift payloads implement the Pinchable typeclass.

Given the Thrift struct,

struct Person {
    1: required string name
    2: optional i64 dateOfBirth

You can write a Pinchable instance like so,

data Person = Person { name :: Text, dateOfBirth :: Maybe Int64 }
    deriving (Eq)

instance Pinchable Person where
    type Tag Person = TStruct
    -- The Tag tells the system that this represents a struct.

    pinch (Person name dateOfBirth) =
        struct [1 .= name, 2 ?= dateOfBirth]

    unpinch value =
        Person <$> value .:  1
               <*> value .:? 2

Better yet, you can drive an instance automatically.

{-# LANGUAGE DeriveGeneric, DataKinds #-}
import GHC.Generics (Generic)

data Person = Person
    { name        :: Field 1 Text
    , dateOfBirth :: Field 2 (Maybe Int64)
    } deriving (Eq, Generic)

instance Pinchable Person

Objects can be serialized and deserialized using the encode and decode methods. These methods accept a Protocol as an argument.

decode binaryProtocol (encode binaryProtocol person) == person

For more information, check the documentation and the examples.

Supported Protocols

The following Thrift protocols are supported:

  • Binary
  • Compact

Supported Transports

The following Thrift transports are supported:

  • Framed
  • Unframed

Code Generation

If you prefer to generate Haskell code from the Thrift files instead of writing the necessary Haskell code by hand, you can use the experimental pinch-gen code generator to do so. For further details see .

Changes (2023-04-27)

  • Allow vector 0.13. (#53) (2022-10-12)

  • Support GHC 9.4. (#50) (2021-12-14)

  • Require network >= (2021-12-04)

  • Allow semigroups 0.20 (2021-11-14)

  • Support GHC 9.2. (#45) (2021-01-14)

Breaking changes:

  • The protocol parsers now use the cereal library and the Pinch.Protocol.Parser module has been removed. Custom protocol implementations need to be ported to the cereal parsers. (#28)
  • Use new header format for binary protocol. This fixes some compatibility issues with thrift libraries for other languages. (#33)

Other changes:

  • Add implementations of the framed/unframed transports (Pinch.Transport, #29).
  • Add Thrift RPC client/server functionality (Pinch.Server/Pinch.Client).
  • A new code generator, pinch-gen, is available. It can generate code from Thrift files for use with the pinch library. For more details, see (2020-12-29)

  • Compatibility with GHC 8.10 (2019-09-25)

  • Introduce decodeWithLeftovers for receiving unparsed portions of the provided bytestring. (2019-02-20)

  • Bounds bumps (2018-11-11)

  • Support GHC 8.6 (#20). (2018-06-15)

  • Add Semigroup instances for some internal types. This improves GHC 8.4 compatibility. (2017-06-03)

  • Compact: Fixed bug which caused incorrect encoding of doubles. (2017-05-13)

  • Support GHC 8.2 (#14). (2017-01-12)

  • Bump upper bound for vector (#11). (2016-07-12)

  • Compile on 32-bit systems. (2016-06-02)

  • Add support for the Thrift Compact Protocol (#2).
  • Add support for returning the leftover ByteString when parsing Thrift payloads (#3). (2016-07-12)

  • Compile on 32-bit systems. (2016-05-23)

  • Build with GHC 8. (2015-12-27)

Breaking changes:

  • unpinch no longer returns Either String a. Instead it returns a Parser a.
  • Protocol.serialize* methods no longer produce a ByteString.Builder and the serialized length. Instead, they produce a custom Builder type.

Other changes:

  • Improve deserialization performance significantly by getting rid of unnecessary calls to Data.Typeable.{eqT, cast}.
  • Improve serialization performance by allocating the output buffer in one go rather than using ByteString.Builder.
  • Improve serialization and deserialization performance further by changing the intermediate representation of lists, sets, and maps. (2015-12-27)

  • Loosen vector version constraint. (2015-11-15)

  • Fixed recursion in C pre-processor expansion. This can break the build on some systems. (2015-11-15)

  • Initial release.