Skip to content

Latest commit

 

History

History
 
 

docs

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

Getting Started with Thrift in Haskell

Thrift has two components, the compiler and the libraries. The compiler is used to generate serialization and server/client code for the services you define in your Thrift files. The generated code depends on the Thrift libraries for networking and serialization primitives.

Getting Started

The first step to using Thrift is to write some Thrift code in a source file. You can start by defining some simple structs and enums:

user.thrift

enum Pet {
  Dog = 0,
  Cat = 1,
}

struct User {
  0: string name,
  1: Pet pet,
}

Each named enum value must have a unique 32-bit integer value associated with it and each struct field must have a unique 16-bit integer ID. These are used in the serialization protocol. Now that you have some Thrift code, you can use your new data structure in Haskell by invoking the Thrift Compiler:

$ thrift-compiler user.thrift

This will generate a Haskell source file called User/Types.hs which contains the Haskell definitions of the data structures you defined as well as the code to serialize and deserialize those data structures. While the real generated code is somewhat complicated, it would look roughly like this for the above example:

data Pet = Pet_Dog | Pet_Cat

data User = User
  { user_name :: Text
  , user_pet :: Pet
  }

You can use these data types like any other Haskell data types by importing User.Types. In addition, you can serialize then to ByteStrings using one of the Thrift serialization formats. For example, if you wanted to serialize a User to JSON, you could do it like this:

import Thrift.Protocol.JSON

userBytes :: ByteString
userBytes = serializeJSON $ User "Joe" Pet_Dog

The serialized bytes can then be deserialized into structured data in any other Thrift-supported language such as C++, Python, or Java.

Remote Procedure Calls

In addition to data structures, you can also define services and remote procedure calls in a Thrift file. Consider the following code that we will add to user.thrift:

service UserFetcher {
  User getUser(0: i64 id)
}

This defines a service called UserFetcher with a single RPC what takes in a 64-bit integer user ID and returns information about the user. Running the Thrift Compiler in the same way as we did above will now result in two additonal files getting create called User.UserFetcher.Client and User.UserFetcher.Server. The client contains all the code that you need to make RPC calls to a running UserFetcher server. The server file contains stubs so that you can create your own implementation of the server functions.

For more detailed examples of how to create servers and clients, see the code in lib/test/SocketChannelTest.hs.

More Details

In this directory, you will find information on how to work with the code that gets generated by the Thrift compiler. This includes:

  • Types: How Thrift types map to Haskell types
  • Names: How Thrift named types and fields in Thrift map to Haskell data types
  • Annotation: Special ways to customize the generated code
  • Options: Thrift compiler flags to alter the generated code
  • Serialization: Which serialization formats are available and how to use them