FP -> Compilers -> Logic -> Blog 2021-05-17T14:38:SZ Luc Tielen https://luctielen.com/ Combining folds using semigroups https://luctielen.com/posts/combining_folds_using_semigroups In today's post, I will show how to combine many recursion-scheme folds using semigroups. For seasoned Haskellers using the library, this trick might be well known or obvious, but I decided to write it down anyway for the rest of us mere mortals 😃. I will assume a little familiarity with recursion-schemes though. If this isn't the case, be sure to check out the (recently revised) recursion-schemes README for an introduction to the library.

## The naive or straightforward approach

For our running example, let's take the idea of "static analysis" in a compiler. Here, the compiler executes many checks to make sure a program is semantically valid. Implemented in a straightforward way, each check is an (effectful) function that does a full traversal of the program AST to collect the analysis results. If we simplify this idea, we end up with the following:

``````import Data.Functor.Foldable
import Data.Functor.Foldable.TH

-- Our AST data type:
data Expr
= Constant Int
| Add Expr Expr

makeBaseFunctor ''Expr

-- 1 + 2 + 3
expr :: Expr
expr = Constant 1 `Add` Constant 2 `Add` Constant 3

-- An analysis pass is an effectful function (here IO is used
-- to print to the terminal):

-- Two effectful functions that we want to combine:
function1, function2 :: ExprF (IO ()) -> IO ()
function1 = function "function1:"
function2 = function "function2:"

-- An effectful function, prints out a prefix + a textual description
-- of each node it encounters.
function :: String -> ExprF (IO ()) -> IO ()
function prefix = \case
ConstantF x ->
putStrLn \$ unwords [prefix, "Constant", show x]
AddF action1 action2 -> do
action1
putStrLn \$ unwords [prefix, "Add"]
action2

main :: IO ()
main = do
putStrLn "Running function1:"
results1 <- cata function1 expr
putStrLn "Running function2:"
results2 <- cata function2 expr
-- ... do something with results``````

Running the snippet above gives us the following output:

``````\$ stack run  # Assuming we are in a stack project
Running function1:
function1: Constant 1
function1: Add
function1: Constant 2
function1: Add
function1: Constant 3
Running function2:
function2: Constant 1
function2: Add
function2: Constant 2
function2: Add
function2: Constant 3``````

You can see that each traversal happens one after the other. Ideally though, we would like to collect all analysis results using a single traversal/fold. Let's try and figure out how we can achieve that.

## Attempt 1: Using function composition

Others have already thought of ways to compose folds using recursion schemes. Tim Williams has a great presentation about recursion schemes where he shows techniques for composing them. First of, there's sequential composition:

``````-- Note: not valid Haskell, '=' is mathematical equality
cata f . cata g = cata (f `comp` g) where
-- 'comp' first applies the function 'y', unwraps a single layer of
-- the Fix datastructure, and then finally applies the function 'x'
comp :: (f (Fix f) -> Fix f)
-> (g (Fix f) -> Fix f)
-> g (Fix f)
-> Fix f
comp x y = x . unfix . y``````

However, this approach is not applicable for our static analysis running example due to the types not lining up. The result of the first function (`g` / `y`) needs to return a datastructure wrapped in `Fix` (but we return a `IO ()` value).

The second approach Tim mentions (using the `(&&&)`-operator from `Control.Arrow`) is applicable:

``````cata f &&& cata g = cata alg where
-- f :: f a -> a
-- g :: f b -> b
alg :: f (a, b) -> (a, b)
alg = f . fmap fst &&& g . fmap snd``````

For "simple" values, this works great. However, this approach has the same problem as before when you return a function or monadic result instead. To illustrate this, let's run the snippet below:

``````-- Note that alg returns a tuple of two IO actions now, instead of one!
alg :: ExprF (IO (), IO ()) -> (IO (), IO ())
alg = (function1 . fmap fst) &&& (function2 . fmap snd)

main :: IO ()
main = do
let (action1, action2) = cata alg expr
action1
putStrLn "action1 finished, now action2:"
action2``````

This gives us the following output:

``````\$ stack run
function1: Constant 1
function1: Add
function1: Constant 2
function1: Add
function1: Constant 3
action1 finished, now action2:
function2: Constant 1
function2: Add
function2: Constant 2
function2: Add
function2: Constant 3``````

This is the same behavior as we had before. We perform only one fold now, but then we still have to run the actions separately. That's not what we want! Back to the drawing board!

## Attempt 2: Using semigroups

We tried some forms of composition so far that didn't work out, but luckily Haskell has many more ways of composing expressions together. One that is often used is `(<>)` / `mappend` from the `Semigroup` typeclass. Here's what that looks like:

``````main :: IO ()
main = cata alg expr where
-- alg / function1 / function2 are a Semigroup because:
-- A function is a Semigroup if it's result is a Semigroup;
-- 'IO a' is a Semigroup if 'a' is a Semigroup;
-- () is a Semigroup.
alg :: ExprF (IO ()) -> IO ()
alg = function1 <> function2``````

Effectively, this calls the 2 functions in a row, and then combines the results. Running this code shows all effectful actions are interleaved as we'd expect:

``````\$ stack run
function1: Constant 1
function2: Constant 1
function1: Add
function2: Add
function1: Constant 2
function2: Constant 2
function1: Add
function2: Add
function1: Constant 3
function2: Constant 3``````

Great! This is exactly what we want. We do only one fold over the datastructure and all actions are interleaved!

## Other monads than IO

While the approach using semigroups is short and sweet, it is not always possible to use it directly. This is because the monad that is being used needs to have a Semigroup instance (and IO just so happens to have an implementation for it). With a little more code, we can work around this limitation:

``````compose :: (Monad m, Semigroup b) => (a -> m b) -> (a -> m b) -> a -> m b
compose f g a = do
result1 <- f a
result2 <- g a
pure \$ result1 <> result2

-- Or using applicative notation:
compose' :: (Applicative f, Semigroup b) => (a -> f b) -> (a -> f b) -> a -> f b
compose' f g a = (<>) <\$> f a <*> g a

-- If you only care about side effects, you could use (*>)
-- instead of (<>) as well.

main :: IO ()
main = cata alg expr where
alg = compose function1 function2``````

With the "compose" function, you can now also use the same approach for monads that don't implement Semigroup (such as Reader/State/...). Nice!

## Wrapping up

In this article I showed 3 approaches to combining many smaller folds into one fused fold. Though not all approaches may be applicable for a specific situation, there are always multiple options to choose from when combining functions in this way.

I need to point out that while I used the recursion-schemes library, the same approach is possible if you use "normal" recursive functions (but maybe with a little more work).

If you are interested in more content like this, follow me on Twitter. Feel free to contact me if you have any questions or comments about this topic.

]]>
Supercharge your handles using phantom types https://luctielen.com/posts/supercharge_your_handles_with_phantom_types In this article, I show how to use phantom types in combination with the "Handle pattern" to create more type-safe and user-friendly APIs in Haskell. I do this based on my experience adding this idea to the souffle-haskell library.

## A quick recap

Jasper van der Jeugt has blogged about the handle pattern in the past. In summary, he recommends using handles when interfacing external services (such as a database or file) with Haskell. A handle type should be created representing access to that service; as well as functions for communicating with the external service using that handle.

Here's what the handle pattern could look like for an external key-value store:

``````-- Internals of the handle data type are opaque for external users
data DBHandle

get :: DBHandle -> Key -> IO (Maybe Value)
put :: DBHandle -> Key -> Value -> IO ()``````

## Applying the handle pattern to souffle-haskell

In the souffle-haskell library, the handle pattern also turned out to be a great fit. The library exposes functionality for communicating with the Souffle Datalog language, which can be viewed as an external resource. Here's what the top level API looks like (simplified):

``````-- Handle type for communicating with the external Datalog program.
data Handle = ...

-- Monad for performing Souffle-related actions in.
newtype SouffleM = ...

-- Many different functions for communicating with Souffle.
-- Note how all of these functions take a handle as an argument.
addFact :: Fact a => Handle -> a -> SouffleM ()
getFacts :: Fact a => Handle -> SouffleM [a]
run :: Handle -> SouffleM ()
-- Many other similar functions..

-- A function for running actions in the SouffleM monad.
-- Given a function that takes a handle as input and returns an action
-- in the SouffleM monad, this function will return the underlying IO action
-- that will perform all these Souffle-related actions.
runSouffle :: (Handle -> SouffleM a) -> IO a``````

The handle pattern helped to structure the API and to take care of resource management. However, you can still mis-use this API. For example, since facts have to be pre-defined for a Souffle program, it doesn't make sense to add a fact to a Souffle program that doesnt' understand it. Can we do better and prevent these kinds of logical mistakes?

## Enter the phantom types

If you take a look at the previous Haskell snippet, you will see that every function takes the handle datatype as an argument. This makes it a great candidate for doing compile-time checks based on type level information. To see how we could do this for the snippet above, let's first introduce a phantom type variable to our handle:

``````{-# LANGUAGE RoleAnnotations #-}

-- "prog" is a type variable referring to a corresponding Datalog program
data Handle prog = ...
-- The next line is needed to prevent users from coercing between
-- handles with different phantom types:
type role Handle nominal

newtype SouffleM = ...

addFact :: Fact a => Handle prog -> a -> SouffleM ()
getFacts :: Fact a => Handle prog -> SouffleM [a]
run :: Handle prog -> SouffleM ()

-- Here we add an extra argument, so that Haskell can infer what type the
-- phantom type of the handle should be.
-- Note: another approach is to use "TypeApplications" (doesn't require an
-- extra argument) to tell Haskell what the type of "prog" should be.
runSouffle :: prog -> (Handle prog -> SouffleM a) -> IO a``````

This phantom type variable by itself doesn't do that much yet except for catching some type errors, but it does give us a starting point to start adding information on the type-level. One way to do this is by adding a constraint (based on the phantom type) to limit the possible scenarios a function can be used in. Conceptually this looks as follows:

``myConstrainedFunc :: MyConstraint prog => Handle prog -> SouffleM ()``

## Taking it a step further with TypeFamilies

For simple usecases the above would suffice, but we need some more expressivity if we want to check that a fact isn't part of a Souffle program. To achieve this, we can make use of a combination of the TypeFamilies extension and "TypeError" in GHC to create sophisticated constraints at the type-level:

``````-- Add these extensions to top of the file.
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE UndecidableInstances #-}

-- With the approach introduced here, some type families will only
-- return a constraint in the error cases (containing a TypeError).
-- GHC will thus think the constraints are redundant.
-- This turns off that warning.
{-# OPTIONS_GHC -Wno-redundant-constraints #-}

import Data.Kind (Type)
import GHC.TypeLits

-- Elem is a type family that checks if a type is contained in a
-- list of types. It returns a type-level boolean.
type Elem :: Type -> [Type] -> Bool
type family Elem a as where
Elem _ '[]       = 'False
Elem x (x ': _)  = 'True
Elem x (_ ': xs) = Elem x xs

-- Example usage of Elem: x won't compile when you try to use it
-- However this gives us a rather cryptic error message:
--  • Couldn't match type ‘'False’ with ‘'True’
--      arising from a use of ‘x’
x :: Elem Int '[Char, Bool] ~ 'True => Int
x = 1234

-- To improve this, let's add a type-level assertion.
-- If the assertion is satisfied, everything is ok.
-- If the assertion fails, a custom type error is returned to the user.
type Assert :: Bool -> ErrorMessage -> Constraint
type family Assert condition message where
Assert 'True _ = ()
Assert 'False msg = TypeError msg

-- Example using Assert: y won't compile if a is not of type Bool,
-- giving us a custom type error instead.
constrainedId :: Assert (Elem a '[Bool]) ('ShowType "This won't compile!")
=> a -> a
constrainedId = id``````

It is now possible to write a check to see if a fact is contained in a Souffle program:

``````-- Type family for declaring which fact types belong to a Souffle program
type ProgramFacts :: Type -> [Type]
type family ProgramFacts a

-- The actual check to see if a program contains a certain fact type
type ContainsFact :: Type -> Type -> Constraint
type family ContainsFact prog fact where
ContainsFact prog fact =
Assert (Elem fact (ProgramFacts prog))
('ShowType "Unknown fact for Souffle program")``````

We can now add this type-level assertion to our initial Haskell snippet:

``````addFact :: (Fact a, ContainsFact prog a) => Handle prog -> a -> SouffleM ()
getFacts :: (Fact a, ContainsFact prog a) => Handle prog -> SouffleM [a]

-- Rest unmodified..

-- In our application code we can specify that Fact1 and Fact2 belong to
-- the Souffle program managed by 'MyProgram':

data MyProgram = MyProgram
data Fact1 = Fact1 String
data Fact2 = Fact2 String

type instance ProgramFacts MyProgram = '[Fact1, Fact2]``````

If we now try to add a fact to a Souffle program that doesn't understand it, it won't compile anymore. Great!

## Conclusion

Phantom types are a lightweight and powerful technique for adding more type-safety to your code. Combined with the handle pattern and type families, it allows you to write expressive type-level assertions that are verified by the compiler.

Like mentioned before, the code in the post is based on my souffle-haskell library. I simplified the types in this post to keep the mental overhead as minimal as possible. Here's the original commit where I introduced the idea in the code.

If you are interested in more content like this, follow me on Twitter. Feel free to contact me if you have any questions or comments about this topic.

]]>
Calling C++ from Haskell https://luctielen.com/posts/calling_cpp_from_haskell In today's blogpost, I will show an approach for calling C++ code from Haskell. This can be useful in case you need the extra performance from C++ or if there is no library in the Haskell ecosystem that provides the functionality you need (but there is a C++ library for it).

The code snippets in this article are kept "simple" (though I will assume some C++ knowledge, since you will need to write some extra C++ code when binding to Haskell). The examples are derived from my souffle-haskell library, where I had to write Haskell bindings to interact with the Soufflé datalog language.

## Binding to C++

If a library is meant to be used from many other languages, most of the time it will provide a C API for doing so. C has a relatively small feature-set and a well-defined, stable ABI (binary interface). On top of that, most languages have good support for interacting with C via a foreign function interface (FFI), making it straight-forward to interface with C.

However, for some libraries this is not the case. Soufflé for example provides only a C++ interface. C++ is a lot bigger language compared to C, has no stable ABI between different versions / compilers and contains many complex features such as overloadable functions and operators, templates, destructors, ... This makes binding to it a lot more complicated than C.

The trick is to write an extra layer between the existing Haskell and C++ code, that exposes functionality using the C ABI. Fortunately, C++ offers an easy way to be compatible with the C ABI with the extern keyword. The snippet below defines a function "answer_to_everything" that can be called from C (and thus also from other languages!):

``````extern "C" {
int answer_to_everything(bool arg);

int answer_to_everything(bool arg) {
return 42;
}
}``````

When using extern, you can still use C++-specific functionality inside the body of a function, but the signature of the function needs to be compatible with C.

If you wanted to, you could now start using this function in Haskell after importing it with a so-called foreign import:

``````foreign import ccall unsafe "answer_to_everything" answerToEverything
:: CBool -> CInt``````

A foreign import is Haskell's way of importing C-compatible functions. Note that unlike Haskell modules, you will need to import foreign functions on a per-function basis. The syntax is as follows:

• foreign import ccall: We're importing a foreign function!
• unsafe: This tells the Haskell compiler that the foreign function will not call back into Haskell. This results in less overhead when crossing language boundaries but you should only use the keyword when this is really the case!
• "answer_to_everything": The name of the function (as defined in C++)
• answerToEverything: The name of the function (in Haskell)
• Type signature: You need to manually add a type signature here, using the types defined in Foreign.C.Types. Depending on if the function is pure or not, you also should wrap the result in IO. The Haskell compiler blindly trusts you as a programmer to provide the correct signature. If you make a mistake here, bad things will happen™️, so be sure to get it right.

### Memory management and objects

Now that we know how to cross the language border and use a simple C++ function from Haskell, we can focus on other more complicated concepts.

First of all, there's memory management. Haskell uses a a garbage collector to clean up unused memory automatically. This is in contrast with C++, which is much "closer to the metal". C++ gives you very fine-grained control of the memory layout of an object and when exactly to allocate or free the memory of an object. If we want to bind C++ to Haskell, we have to make sure both languages work well together. One way to achieve this is by letting Haskell be in charge and call into the C++ code. Objects used via the FFI need to be allocated on the C++ heap, so they don't automatically get cleaned up once the object goes out of scope (like stack-allocated objects would). After objects are no longer in use, they need to be cleaned up again (also from the Haskell side).

The next issue are the objects themselves. The C ABI has no support for objects or calling methods on those objects. This isn't a problem though, since objects can be represented as an (opaque) C-like struct, together with functions that perform actions with that struct. Each of the functions has the same signature as the corresponding method of the object, except the function takes an additional argument for the pointer to the object. (In C++ this is handled implicitly for you with the this pointer.) Constructors and destructors also need to have their own separate functions in the FFI.

Taking all this into account, our FFI layer for managing a C++ object could look like this:

``````// Suppose we want to call into this object from Haskell:

class Example {
public:
// Note: Constructor and destructor are auto-generated here!
// We will have to add functions for calling these as well.
bool do_stuff(int arg);
};

// We can define the following FFI layer:

// in ffi.h
extern "C" {
typedef struct ffi_example;

ffi_example* example_create();
void example_destroy(ffi_example* object);
bool example_do_stuff(ffi_example* object, int arg);
}

// in ffi.cpp
#include "ffi.h"

extern "C" {

ffi_example* example_create() {
auto object = new Example();
return reinterpret_cast<ffi_example*>(object);
}

void example_destroy(ffi_example* object) {
auto example = reinterpret_cast<Example*>(object);
delete example;
}

bool example_do_stuff(ffi_example* object, int arg) {
auto example = reinterpret_cast<Example*>(object);
return example->do_stuff(arg);
}

}``````

Now that we have the C++ part, we still need to write the Haskell part. To do this, we use an API from the Haskell base library for interacting with foreign functions. It provides data types that have a 1-to-1 correspondence with their C equivalents (for example CInt, CBool, ...). The Ptr data type is used for managing pointers from Haskell. The Ptr type uses a phantom type variable as a type-level tag to detect at compile time if you use a pointer of an unexpected type.

You may have noticed in the last C++ snippet that there was a manual call to delete. This is frowned upon in C++ nowadays since it can be very easy to make a mistake and forget to call delete in certain code paths (for example if an exception occurred). C++ has a solution for this in the form of so-called smart pointers but those are unusable in combination with the FFI. Haskell has a very similar mechanism though, called foreign pointers. A foreign pointer is a pointer managed by the Haskell runtime / garbage collector, coupled with a finalizer function for freeing up the memory used by the pointer. When the foreign pointer goes out of scope and there are no more references to it in the Haskell runtime, it will call the finalizer function.

Continuing with the Example class from earlier, we can now make sure the destructor is always called when the object goes out of scope:

``````-- An empty data type, used as a type tag for the Ptr type
data Example

foreign import ccall unsafe "example_create" exampleCreate
:: IO (Ptr Example)
-- Slightly different syntax, this gives us a function pointer to the
-- "example_destroy" function (needed below):
foreign import ccall unsafe "&example_destroy" exampleDestroy
:: FunPtr (Ptr Example -> IO ())
foreign import ccall unsafe "example_do_stuff" exampleDoStuff
:: Ptr Example -> CInt -> IO CBool

-- This initializes a Example object on the heap, that will be
-- cleaned up with "exampleDestroy" when it is no longer in use.
mkExample :: IO (ForeignPtr Example)
mkExample = mask_ \$ do
-- mask_ is needed to avoid leaking the pointer in case an async exception
-- occurs between allocation and wrapping it in a foreign pointer.
ptr <- exampleCreate
newForeignPtr exampleDestroy ptr

main :: IO ()
main = do
obj <- mkExample
-- Now we can use the pointer by unwrapping it with "withForeignPtr":
withForeignPtr obj \$ \ptr -> do
result <- exampleDoStuff ptr 1234
print result  -- Process the result.``````

### Overloads

C++ has support for overloadable functions (functions with the same name and scope, but with different type signatures and function bodies). However, this is again not supported in C and as such is not possible to do in the FFI. If we want to be able to call these overloads, we have to wrap each variant with a helper function that is exposed in the FFI. If we add an overload to our Example class defined earlier, we can expose overloaded functions as follows:

``````class Example {
public:
bool do_stuff(int arg);
bool do_stuff(float arg);  // <- This overload is new.
};

// in ffi.h
extern "C" {
// Rest of code is same as before.

// The FFI functions all need a unique name.
bool example_do_stuff_int(ffi_example* object, int arg);
bool example_do_stuff_float(ffi_example* object, float arg);
// ... add other variants as needed.
}

// in ffi.cpp
#include "ffi.h"

extern "C" {
// Rest of code is same as before.

bool example_do_stuff_int(ffi_example* object, int arg) {
auto example = reinterpret_cast<Example*>(object);
return example->do_stuff(arg);  // calls the overload with int argument
}

bool example_do_stuff_float(ffi_example* object, float arg) {
auto example = reinterpret_cast<Example*>(object);
return example->do_stuff(arg);  // calls the overload with float argument
}

}``````

Finally, each variant has to be imported on the Haskell side:

``````-- Rest of code is same as before.

foreign import ccall unsafe "example_do_stuff_int" exampleDoStuffInt
:: Ptr Example -> CInt -> IO CBool
foreign import ccall unsafe "example_do_stuff_float" exampleDoStuffFloat
:: Ptr Example -> CFloat -> IO CBool``````

### Loops

So far we focused on a single object or data type, but what about multiple objects? In C++ for- or while-loops are used to iterate over collections of data. Loops, like the other concepts mentioned before, will require some massaging into a different format until we have something that can be used from the FFI.

Let's update our previous example to have a collection of some sort:

``````class Example {
private:
// Example now contains a collection of data
std::vector<int> values;

public:
// To keep things simple, we initialize the vector to
// a collection of 3 hardcoded values.
Example() : values({1, 2, 3}) {}

auto& get_values() const {
return values;
}
};

// We can now loop over the data:

Example example;
auto& values = example.get_values();

for (auto& value : values) {
process_value(value);
}``````

The example makes use of a range-based for-loop, which was introduced in C++11. Range-based loops are a form of syntactic sugar and can be rewritten using C++ iterators as follows:

``````// Note: "it" is short for iterator
for (auto it = values.begin(); it != values.end(); ++it) {
auto& value = *it;
process_value(value);
}``````

While we're at it, a standard for-loop is also sugar for a while-loop. Let's do another transform:

``````auto it = values.begin();
while (it != values.end()) {
auto& value = *it;
process_value(value);
++it;
}``````

This is starting to come close to something that we can use from the FFI, we only need to write some functions for calling each of the steps of the loop separately:

``````auto it = ffi_iterator_create(values);
while (ffi_iterator_has_next(it)) {
auto& value = ffi_iterator_next(it);
std::cout << value << std::endl;
}
ffi_iterator_destroy(it);``````

Writing each of the helper functions is quite a bit of work, but is based on ideas mentioned earlier in this blogpost:

``````// in ffi.h

struct ffi_iterator;  // New struct for iterating over the collection.

ffi_iterator* ffi_iterator_create(ffi_example* obj);
void ffi_iterator_destroy(ffi_iterator* it);
bool ffi_iterator_has_next(ffi_iterator* it);
int ffi_iterator_next(ffi_iterator* it);

// in ffi.cpp

struct ffi_iterator {
using iterator_t = std::vector<int>::iterator;

// We need to keep track of what the iterator is currently pointing to,
// as well as the end of the collection.
iterator_t iterator;
const iterator_t end;

ffi_iterator(const iterator_t& begin_, const iterator_t& end_)
: iterator(begin_)
, end(end_) {}
};

ffi_iterator* ffi_iterator_create(ffi_example* obj) {
// We get the collection out of the object,
// and get the iterators pointing to beginning and end.
auto example = reinterpret_cast<Example*>(obj);
auto& values = example.get_values();
return new ffi_iterator(values.begin(), values.end());
}

void ffi_iterator_destroy(ffi_iterator* it) {
delete it;
}

bool ffi_iterator_has_next(ffi_iterator* it) {
// There is a next value if the iterator is not pointing to the end.
return it->iterator != it->end;
}

int ffi_iterator_next(ffi_iterator* it) {
// Get the current element, then update iterator to next element.
auto& value = *it->iterator;
++it->iterator;
return value;
}``````

Once we have these functions, we can build our own loop in Haskell and process the values there:

``````data ExampleIterator

foreign import ccall unsafe "ffi_iterator_create" ffiIteratorCreate
:: Ptr Example -> IO (Ptr ExampleIterator)
foreign import ccall unsafe "&ffi_iterator_destroy" ffiIteratorDestroy
:: FunPtr (Ptr ExampleIterator -> IO ())
foreign import ccall unsafe "ffi_iterator_has_next" ffiIteratorHasNext
:: Ptr ExampleIterator -> IO CBool
foreign import ccall unsafe "ffi_iterator_next" ffiIteratorNext
:: Ptr ExampleIterator -> IO CInt

mkExampleIterator :: Ptr Example -> IO (ForeignPtr ExampleIterator)
mkExampleIterator ptr =
mask_ \$ newForeignPtr ffiIteratorDestroy =<< ffiIteratorCreate ptr

-- Helper function for looping over the data and collecting the results on
-- the Haskell side.
collectValues :: Ptr ExampleIterator -> IO [CInt]
collectValues = go [] where
go acc iterator = do
CBool hasNext <- ffiIteratorHasNext iterator
if hasNext == 1
then do
value <- ffiIteratorNext iterator
go (value : acc) iterator
else pure acc

main :: IO ()
main = do
obj <- mkExample
withForeignPtr obj \$ \objPtr -> do
iterator <- mkExampleIterator objPtr
withForeignPtr iterator \$ \iteratorPtr -> do
values <- collectValues iteratorPtr
-- Now you can process the values like you would
-- for any other Haskell value.
print \$ map (+1) values``````

### Compiler flags

That's it for the code part, but we're not finished quite yet! Because we are using 2 languages, we need to provide compilation flags for both Haskell and C++. This can be done in your project's package.yaml / cabal file / stack.yaml.

For example, in the souffle-haskell library, the package.yaml contains additional configuration instructing the C++ compiler to look for files in the cbits directory and use the given C++ compiler flags:

``````cxx-sources: cbits/*.cpp
include-dirs:
- cbits
- cbits/souffle
cxx-options:
- -std=c++17
# Provide other C++ compilation flags here as necessary.``````

Note that you should not use cpp-options in the yaml file. This refers to the Haskell C-preprocessor config and does not refer to C++-options like I initially assumed.

Depending on the C++ code you are binding to, you may also need to add specific compiler flags for certain C++ compilers or operating systems. In package.yaml this can be done as follows:

``````when:
- condition: os(darwin)
extra-libraries: c++``````

## Conclusion

This post turned out much larger than I initially expected! I guess this shows that binding to C++ is more work than C, but can definitely be done. The code in some snippets is simplified to avoid making this blog post even longer. If you are interested in what a "real" example of this approach looks like, check out my souffle-haskell library. You can find the most relevant files for binding to C++ here, here and here.

One final thing to mention is that this approach isn't specific to Haskell, you would only need to swap out the Haskell code with your language of choice to bind to the underlying C++ code.

If you are interested in more content like this, follow me on Twitter for blogpost updates or subscribe to the RSS feed.

]]>
How to set up your blog with Haskell, Slick and Netlify https://luctielen.com/posts/how_to_setup_blog_with_haskell_slick_and_netlify I wanted to setup a blog powered by Haskell and HTML/CSS and host it on Netlify. Creating a static site is easy enough using Slick, but this has no direct support for Netlify. In this first post I will show you how to fix that.

## Tech stack

I wanted my blog to be easy to setup, minimal and extensible. In the past I've tried (and failed) setting up a blog because I never managed to finish the initial setup due to a complicated setup. After some googling around, I came across the Slick static site generator. Slick is written in Haskell and uses Pandoc + the Shake build system to compile all files into a static site. Slick assumes some Haskell knowledge but with the documentation you can have a first version of your blog up and running in a few minutes if you use the default project template.

After I got the blog up and running, it was time to give the website it's own look and feel. I started with a standalone HTML and CSS file and played around with the styling. Once I was happy with how the site looked, I replaced the templates and CSS that Slick provides by default with my own. The code for this blog can be found on Github. The "site/" directory contains all templates / CSS / markdown used to generate this blog.

Generating the blog is as simple as running the following command:

``\$ stack run``

This will put the generated files in the output folder you configured in "app/Main.hs".

## Deploying the site

Now that I had the blog up and running, I still needed to deploy it somewhere. For this, I chose Netlify since it is often used for hosting static sites. Unfortunately though, Netlify has no direct support for Slick! To solve this, I wrote a small bash script that builds the blog and commits all necessary files from the blog into a separate orphan branch named "deploy":

``````#!/bin/bash

# Run this script locally to trigger a build and deploy.
# It assumes the "deploy" branch already exists
# (create with "git checkout --orphan deploy")

set -e

echo "Generating blog..."
stack run
tar czf build.tar.gz build/

echo "Updating blog content..."
git checkout deploy
rm -rf build/
tar xzf build.tar.gz
rm build.tar.gz

echo "Deploying blog..."
git add build/
git commit -m 'Deploy new version'
git push

git checkout -

exit 0``````

On the Netlify side, I configured it to trigger a deploy of the blog if a push was made to the "deploy" branch.

Last step was buying the domain name and linking it to my netlify app. I would suggest to buy the domain name via Netlify as well, for the easiest setup. For more information, see the official Netlify docs.

## What's next?

Phew, that was the first blogpost! If you followed along, you should now have your own blog setup! All that's left is to write some blogposts. 😄

So what can you expect on this blog in the future? Most content will be related to functional programming, compilers and logic, with maybe occassionally some other (non-)tech things. You can get updates on this blog if you follow me on Twitter or if you subscribe to my RSS feed.

Stay tuned!

]]>