Haskell OOP style inheritance

In C #, I can declare the following

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)); } 

In Haskell, I would print above as

 data A = A { field :: Int } | B { field :: Int, field2 :: Int } f :: A -> Int f (A a) = a f (B ab) = a + b main :: IO() main = do putStrLn $ show (f(a) + f(b)) where a = A 1 b = B 1 2 

What I don't like about the Haskell colleague is that I have to repeat field twice in the definition of A data (this becomes more tedious as the number of fields present in A increases, which should be in B ). Is there a shorter way in Haskell to write B as a subclass of A (which is somewhat similar to the C # method)?

+4
source share
2 answers

If there are many fields in, one construct that might make sense is to have two different data types for A and B, where B contains A, and then use the type class to define f. For instance:

 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 fa = field1 a + field101 a instance ABC B where fb = f (ab) + field10000 b 
+6
source

Your data definition is a lateral move, both constructors A and B are instances of type A, where what you are looking for is type B, which is type A, not just an instance of type A.

Try:

 data Foo = Foo {field :: Type} newtype Bar = Bar Foo fromBar Bar x = x toBar x = Bar x 

This will allow you to declare all kinds of special functions in the type panel that will not be applied to Foo, as well as work with the bar using functions designed for the Foo type.

If you want to extend the Foo data parameters with additional information in Bar, you can use the data declaration and has-a relationship. This is not as desirable as the new type, since newtype is lazily evaluated where the data declaration is strict. Nonetheless:

 data Foo = Foo {field :: Type} data Bar = Bar {fooField :: Foo, moreField :: Type} 

As sepp2k points out, what you really want to do to determine the β€œnature” of a type is not by how it looks, but by how it works. We do this in Haskell by defining a type class and having an instance of this class.

Hope this helps.

+3
source

Source: https://habr.com/ru/post/1315835/


All Articles