Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#和Haskell之间的沟通_C#_Json_Haskell_Dll - Fatal编程技术网

C#和Haskell之间的沟通

C#和Haskell之间的沟通,c#,json,haskell,dll,C#,Json,Haskell,Dll,我有一个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 :: In

我有一个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字符串并将其传递到另一种语言?

最有效的方法是使用C FFI在Haskell和C#之间建立桥梁。这将是一个很大的工作

另一种方法是使用诸如MessagePack之类的通用序列化协议。这里有一个Haskell库,可以通过MessagePack轻松地与其他语言进行通信:

显然,这种技术有很高的“调用”开销,但它比使用RESTAPI和遍历网络堆栈(当然这是另一种选择)要快得多。只要呼叫开销不是您的瓶颈,那么这是一种完全合理的方法。

您的选择如下:

  • 手动将所有C#/Haskell结构转换为普通C结构或从普通C结构转换为普通C结构。(高性能、编写复杂、调试困难)

  • 手动将C#/Haskell结构序列化/反序列化为JSON/XML/YAML/CSV/whatever。(性能较低,极易调试。)

  • 对于每个数据结构,手动编写并公开知道如何从中提取琐碎数据的函数。(例如,如果您有一个Haskell
    映射
    ,请导出每次提取一个键的函数,其方式非常简单,C可以理解,然后从C#端包装该函数。)


顺便说一句,没有办法“直接”或“自动”让C#理解Haskell对象的布局,反之亦然。

这可能没问题,但可能和做闪亮的新微服务一样慢(我想说的是:如果不是关于速度,而且你对微服务还满意,那么从haskell提供REST服务并在.net/C#中使用它可能会更容易——对于这样的情况,可能最好将其转换为C#,在我看来,更复杂一点的微服务就可以了)FFI允许你将Haskell与C ABI连接起来。为什么是C?因为它是最基本的ABI之一,具有基本类型,并且被许多语言作为自己的“本机语言”使用接口/FFI。因此,您不能真正将复杂类型从Haskell移动到C#,您必须首先将它们封送到C中,编写自定义桥HsCC#。对于Haskell,请参阅c2hs之类的工具,它们可以帮助您编写封送代码。还请参阅您是否已经尝试过“从任何内容调用Haskell”你自己?因为我不能在Windows上用cabal安装它。我在第13期()和第15期()中对此发表了评论。我还没有在Windows上尝试过。我强烈建议你在Windows上使用stack。你说的“Windows上的stack”是什么意思?