Haskell overload function implementation

I am working on the problem of writing Haskell code similar to a C ++ program.

C ++ Code:

class Rectangle { private: int length; int width; public: Rectangle() { length = 0; width = 0; } Rectangle(int x) { length = x; width =0; } Rectangle ( int x , int y) { length = x; width = y; } }; 

To write similar Haskell code, I made a Rectangle data type

 data Rectangle = Rectangle Length Width deriving (Eq, Show , Read) type Length = Int type Width = Int 

Then I was thinking of creating a load function that can act as a constructor. But I do not understand how to implement function overloading with a different number of arguments. Please help. Thanks.

+6
source share
3 answers

Although this overload can be performed in Haskell, it is not considered idiomatic and will most likely lead to confusing errors later. Instead, you should simply define functions that build data:

 point :: Rectangle point = Rectangle 0 0 line :: Length -> Rectangle line l = Rectangle l 0 square :: Int -> Rectangle square a = Rectangle aa 

This allows you to give clear names that describe the semantics of each overload, rather than relying on the number and type of arguments that are given to resolve the differences you have in mind.

However, if you want to write an overloaded version, you can do this easily using types:

 class MakeRectangle a where rectangle :: a instance MakeRectangle Rectangle where rectangle = Rectangle 0 0 instance MakeRectangle (Length -> Rectangle) where rectangle l = Rectangle l 0 instance MakeRectangle (Length -> Width -> Rectangle) where rectangle = Rectangle 

To compile you will need {-# LANGUAGE FlexibleInstances #-} at the top of the file. This trick is used by the standard Text.Printf library, but I would not consider this a particularly good example of overloading in Haskell; almost always there is some structure for the type of the overloaded value, whereas here its whole structure is dictated by the instance, which can become a way to deduce the type; not only that, but there are no reasonable laws that govern instances (indeed, the type is too general to allow any).

But if you really want to do this, you can, and although this is usually a bad idea, sometimes (as in the case of printf ), this is the only way to execute the required interface.

To try this in GHCi, you need to specify the types that you use explicitly, or you will not be able to allow instances:

 GHCi> rectangle :: Rectangle Rectangle 0 0 GHCi> rectangle (1 :: Length) :: Rectangle Rectangle 1 0 GHCi> rectangle (1 :: Length) (2 :: Width) :: Rectangle Rectangle 1 2 
+21
source

To achieve this behavior, you can use write syntax.

 data Rectangle = Rectangle {len :: Length, width :: Width} deriving (Eq, Show , Read) type Length = Int type Width = Int rectangle = Rectangle { len = 0, width = 0 } 

rectangle :: Rectangle will be your constructor here.

Now you can define some Rectangle values:

 Ξ»> let a = rectangle {len = 1} Ξ»> a Rectangle {len = 1, width = 0} 
+22
source

Not what you are looking for simply:

 data Rectangle = Point | Line Int | Rectangle Int Int 
+4
source

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


All Articles