2

I have this Haskell Code:

module RectangleMover where

data Point = Point Int Int deriving (Show)
movePoint :: Point -> Int -> Int -> Point
movePoint (Point x y) dx dy = Point (x + dx) (y + dy)

data Rectangle = Rectangle { corner :: Point, width :: Int, height :: Int } deriving (Show)
move :: Rectangle -> Int -> Int -> Rectangle
move r@(Rectangle {corner=c}) dx dy = r { corner = movePoint c dx dy }

p = Point 1 2
hsRec = Rectangle p 10 20

The equivalent C# code for this would be:

class Point
{
    private int x;

    private int y;

    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public void Move(int dx, int dy)
    {
        this.x += dx;
        this.y += dy;
    }
}

class Rectangle
{
    private Point point;

    private int width;

    private int height;

    public Rectangle(Point p, int width, int height)
    {
        this.point = p;
        this.width = width;
        this.height = height;
    }

    public void Move(int dx, int dy)
    {
        this.point.Move(dx, dy);
    }
}

Point p = new Point(1,2);
Rectangle csRec = new Rectangle(p, 10, 20);

My question now is how to pass the "instance" hsRec Haskell to C# and the csRec from C# to Haskell. The common way in this case would be to create a DLL from Haskell code with the FFI and call this DLL from C#. Also the other way round, creating a DLL from C# and call this DLL from Haskell.

To export from Haskell here is a simple example with integer:

{-# LANGUAGE ForeignFunctionInterface #-}

module Add () where

import Foreign.C.Types

add :: CInt -> CInt -> CInt
add x y = x + y

foreign export ccall add :: CInt -> CInt -> CInt

But how is it possible to pass more complex types between these languages? In this case passing an object of type rectangle. Is it maybe possible to convert an object to a JSON or XML string and pass it over to the other language?

2
  • 1
    it probably would be ok but probably just as slow as doing the shiny new microservice thing (what I'm trying to say: if it's not about speed and you are ok with microservices then it's probably easier to provide a REST service from haskell and consume this in .net/C# - for cases like this it's probably best to just translate it into C#, a bit more complex microservices are fine IMO) Commented Jun 30, 2016 at 9:48
  • 1
    The FFI lets you connect Haskell with the C ABI. Why C? Because it's one of the most basic ABI, with basic types, and which is used by many languages as their own "native" interface / FFI. So, you can't really move complex types from Haskell to C#, you have to marshal them into C first, writing custom bridges Hs<->C<->C#. For Haskell, see tools like c2hs which can help you in writing the marshalling code. Also see wiki.haskell.org/GHC/Using_the_FFI Commented Jun 30, 2016 at 11:00

2 Answers 2

3

Your options here are:

  • Manually convert all your C# / Haskell structures to/from plain C structures. (High performance, complex to write, hard to debug).

  • Manually serialise / deserialise your C# / Haskell structures as JSON / XML / YAML / CSV / whatever. (Lower performance, drastically easier to debug.)

  • For every data structure, manually write and expose functions that know how to fetch trivial data out of it. (E.g., if you have a Haskell Map, export functions for fetching one key at a time, in a way trivial enough for C to understand, and then wrap that from the C# side.)

AFAIK, there's no way to "directly" or "automatically" make C# understand the layout of Haskell objects, or vice versa.

Sign up to request clarification or add additional context in comments.

Comments

2

The most efficient way is to create a bridge between Haskell and C# using the C FFI. That's going to be a lot of work.

Another way is to use a common serialization protocol like MessagePack. Here's a Haskell library that makes it very easy to communicate with other languages via MessagePack: https://github.com/nh2/call-haskell-from-anything

Obviously this technique has a high "calling" overhead, but it will be much faster than using a REST API and going through a network stack (which of course is another option). As long as the calling overhead is not your bottleneck, then this is a perfectly reasonable method.

3 Comments

Did you already try "call-haskell-from-anything" by yourself? Because i can't install it with cabal on Windows. I commented this in issue #13 (github.com/nh2/call-haskell-from-anything/issues/13) and issue #15 (github.com/nh2/call-haskell-from-anything/issues/15).
I haven't tried it on Windows. I highly recommend you use stack on Windows though.
What do you mean with "stack on Windows"?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.