我有这个Haskell代码:
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
这个等效的C#代码是:
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);
我现在的问题是如何将“实例”hsRec Haskell传递给C#,将csRec从C#传递给Haskell。在这种情况下,常见的方法是使用FFI从Haskell代码创建DLL,并从C#调用此DLL。反过来说,从C#创建一个DLL并从Haskell调用此DLL。
要从Haskell导出,这是一个带整数的简单示例:
{-# 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
但是如何在这些语言之间传递更复杂的类型呢?在这种情况下传递一个矩形类型的对象。 是否可以将对象转换为JSON或XML字符串并将其传递给另一种语言?
答案 0 :(得分:3)
您的选择是:
手动将所有C#/ Haskell结构转换为普通C结构。 (性能高,编写复杂,难以调试)。
手动将C#/ Haskell结构序列化/反序列化为JSON / XML / YAML / CSV /等等。 (性能更低,更容易调试。)
对于每个数据结构,手动编写和公开知道如何从中获取普通数据的函数。 (例如,如果你有一个Haskell Map
,导出函数一次获取一个键,以一种微不足道的方式让C理解,然后从C#端包装它。)
AFAIK,没有办法"直接"或者"自动"使C#理解Haskell对象的布局,反之亦然。
答案 1 :(得分:2)
最高效的方法是使用C FFI在Haskell和C#之间创建桥接。这将是一项很多工作。
另一种方法是使用像MessagePack这样的通用序列化协议。这是一个Haskell库,通过MessagePack可以很容易地与其他语言进行通信:https://github.com/nh2/call-haskell-from-anything
显然,这种技术有很高的呼叫能力。开销,但它将比使用REST API和通过网络堆栈(当然这是另一种选择)快得多。只要调用开销不是你的瓶颈,那么这是一个非常合理的方法。