Copyright | (c) Alessandro Bruni 2014 |
---|---|
License | GPL-2 |
Maintainer | albr@dtu.dk |
Safe Haskell | None |
Language | Haskell98 |
Haskell Foreign Function Interface (FFI) for OCaml. Allows integrating OCaml code into Haskell programs: right now the interface is still pretty rough, and there are probably terrible memory holes that we need to deal with, consider it as a proof of concept.
It offers:
- calling OCaml functions from Haskell;
- serialization and deserialization of OCaml datatypes, including
unit
,bool
,int
,double
,string
,list
s,tuple
s andoption
s; - limited automatic suppport for serializing algebraic data types, works when there are no type variables (helper functions are provided for converting between the two representations, so custom serializations can be built)
- strict and lazy evaluation, support for side effects
Current limitations:
- does not support passing higher order functions to OCaml (Haskell function serialization is not supported)
- tuple serialization limited to tuples of 2 to 5 arguments
- no handling of garbage collection, so your program might explode
- caml_startup :: [String] -> IO ()
- class Marshal t where
- deriveMarshalInstance :: Name -> Q [Dec]
- type Value = CLong
- type Tag = CUInt
- register_closure :: Marshal a => String -> a
- block_constructor :: Tag -> [Value] -> Value
- constant_constructor :: Int -> Value
- is_block :: Value -> Bool
- is_value :: Value -> Bool
- get_const :: Value -> Int
- get_field :: Value -> Int -> Value
- get_tag :: Value -> CUChar
Documentation
caml_startup :: [String] -> IO ()
Startup for the OCaml runtime: call this function before using any other function in this module. The list of arguments is fed to the OCaml runtime. For example:
main = do args <- getArgs caml_startup args -- ..rest of the program..
class Marshal t where
Marshal provides functions for transforming a Haskell
representation of data into OCaml and viceversa. Default
implementations are given for all basic types: Unit, Bool,
Int, Float, Double, String; and dependent declarations
allow to construct Marshal implementations for lists, tuples and
applicative types. Note that for applicative types the marshal
function is not implemented, so it is not (yet) possible to pass
higher order values.
marshal
takes a Haskell value of type t
and produces an
opaque OCaml value.
unmarshal
takes an OCaml value and returns its
deserialization into a Haskell data type
Marshal Bool | Converts Bool into |
Marshal Double | Converts an Haskell Double into an OCaml |
Marshal Float | Converts an Haskell Float into an OCaml |
Marshal Int | Represents the |
Marshal String | Converts an Haskell String into an OCaml |
Marshal () | Converts |
Marshal a => Marshal [a] | Converts an Haskell list into an OCaml list. |
Marshal a => Marshal (IO a) | Use the IO monad to mark those functions that produce side effects to the system. The IO monad also enforces strict evaluation, hence the call is executed at the point where the function is called. |
Marshal a => Marshal (Maybe a) | Converts the Maybe monad to the corresponding OCaml datatype. |
Marshal a => Marshal ([Value] -> a) | Allows calling the C function |
(Marshal a, Marshal b) => Marshal (a -> b) | Applicative types: allows calling OCaml functions of type |
(Marshal a, Marshal b, Marshal c) => Marshal (a -> b -> c) | Applicative types: allows calling OCaml functions of type |
(Marshal a, Marshal b, Marshal c, Marshal d) => Marshal (a -> b -> c -> d) | Applicative types: allows calling OCaml functions of type |
(Marshal a, Marshal b) => Marshal (a, b) | Converts an Haskell 2-tuple into an OCaml 2-tuple and viceversa |
(Marshal a, Marshal b, Marshal c) => Marshal (a, b, c) | Converts an Haskell 3-tuple into an OCaml 3-tuple and viceversa |
(Marshal a, Marshal b, Marshal c, Marshal d) => Marshal (a, b, c, d) | Converts an Haskell 4-tuple into an OCaml 4-tuple and viceversa |
(Marshal a, Marshal b, Marshal c, Marshal d, Marshal e) => Marshal (a, b, c, d, e) | Converts an Haskell 5-tuple into an OCaml 5-tuple and viceversa |
deriveMarshalInstance :: Name -> Q [Dec]
Automatically generate an instance of Marshal given a datatype. If you have an OCaml data type with no type variables and multiple constructors:
type t = C1 of int * string | C2 of t * t | C3
Simply produce a corresponding Haskell data type, then call
deriveMarshalInstance
to obtain two way conversion between the
Haskell and OCaml representations:
data T = C1 Int String | C2 T T | C3 $(deriveMarshalInstance ''T)
register_closure :: Marshal a => String -> a
register_closure
returns a closure of type a for any OCaml name
that has been registered with:
let _ = Callback.register "f" f
If f
is a function of OCaml type int -> int
then it can be
registered with:
f = register_closure "f" :: Int -> Int
register_closure
works with type variables as well, as long as
all its instantiations are also instance of Marshal. For example
the function linearize
that takes a tree and returns a list, with
parameter type a
:
type 'a tree = Leaf of 'a | Node of 'a tree * 'a tree;; let rec linearize t = match t with | Leaf(x) -> [x] | Node(l,r) -> let ll = linearize l in let lr = linearize r in ll @ lr;; let _ = Callback.register "linearize" linearize
can be registered as such:
linearize = register_closure "linearize" :: Tree a -> [a]
provided that an implementation of Tree a
and Marshal for both Tree a
and a
exist.
block_constructor :: Tag -> [Value] -> Value
Produces a block constructor, that is, a constructor with arguments. The integer pararmeter is the index of the block constructor, in order of appearance on the declaration of the datatype, counting from 0 and not considering constant constructors.
constant_constructor :: Int -> Value
Produces a constant constructor, that is, a constructor that has no parameters. The integer parameter is the index of the constant constructor, in order of appearance on the declaration of the datatype, counting from 0 and not considering block constructors.
Returns the index for a constant constructor, inverse of
constant_constructor
.
Returns the idnex for a block constructor, more or less an
inverse of block_constructor
, to be used together with get_field