Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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中的OOP风格继承_C#_Oop_Haskell - Fatal编程技术网

C# Haskell中的OOP风格继承

C# Haskell中的OOP风格继承,c#,oop,haskell,C#,Oop,Haskell,在C#中,我可以声明以下内容 class A { int Field; } class B : A { int Field2; } static int f(A a) { return a.Field; } static int f(B b) { return a.Field + b.Field2; } static void Main(string[] args) { A a = new A() { Field = 1 }; A b = new B() {

在C#中,我可以声明以下内容

class A {
    int Field;
}

class B : A {
    int Field2;
}

static int f(A a) { return a.Field; }
static int f(B b) { return a.Field + b.Field2; }

static void Main(string[] args) {
    A a = new A() { Field = 1 };
    A b = new B() { Field = 1, Field = 2};

    Console.WriteLine(f(a) + f(b));
}
在Haskell中,我会将上述内容键入

data A = A { field :: Int } | B { field :: Int, field2 :: Int }

f :: A -> Int
f (A a) = a
f (B a b) = a + b

main :: IO()
main = do putStrLn $ show (f(a) + f(b))
    where a = A 1
          b = B 1 2

我不喜欢Haskell对应项的地方在于,我必须在
A
的数据定义中重复两次
字段(随着
A
中需要在
B
中的字段数量的增加,这会变得更加烦人)。Haskell有没有更简洁的方法将
B
作为
a
的子类编写(这有点类似于C#way)?

如果a有很多字段,一种可能有意义的设计是为a和B使用两种不同的数据类型,其中ab包含a,然后使用typeclass定义f。像这样:

data A = A {field1 :: Int, field2 :: Int, ..., field9999 :: Int}
data B = B {a :: A, field10000 :: Int}

class ABC a where
    f :: a -> Int

instance ABC A where
    f a = field1 a + field101 a

instance ABC B where
    f b = f (a b) + field10000 b

您的数据定义是横向移动,a和B构造函数都是类型a的实例,您要查找的是类型B,它是a类型a,而不仅仅是类型a的实例

尝试:

这将允许您在类型栏上声明不适用于Foo的各种特殊函数,以及使用为类型Foo设计的函数在类型栏上操作

如果您想用Bar中的附加信息扩展Foo的数据参数,可以使用数据声明和has-a关系。这不像newtype那样令人满意,因为newtype在数据声明严格的情况下是惰性地进行计算的。仍然:

data Foo = Foo {field :: Type}
data Bar = Bar {fooField :: Foo, moreField :: Type}
正如sepp2k所指出的,定义类型的“性质”真正需要做的不是它的外观,而是它的工作方式。在Haskell中,我们通过定义一个类型类并使该类具有一个类型实例来实现这一点


希望这能有所帮助。

是的,我想这是一种方法。还要注意,C代码中的
f
是一个重载函数。与继承完全无关,重载函数总是需要定义为类型类。事实上,Haskell的类型类与函数重载比与OOP“类”有更多的共同点。@sepk-我目前在代码中有这种组合方法。我希望我可以避免它,但我认为它将不得不在同一时间。谢谢你的回答@camccann,函数是作为一个例子提供的,如何处理实例和重载方面不是本文的重点,但是感谢您对这两种语言之间关系的见解。感谢您对如何处理这一问题的另一种观点。我现在看到了两种语言在实现目标的心理模型上的差异。解释事物有助于我更好地理解它们
data Foo = Foo {field :: Type}
data Bar = Bar {fooField :: Foo, moreField :: Type}