在Haskell中实现函数重载

Rog*_*ews 6 haskell

我正在研究编写类似于C++程序的Haskell代码的问题.

C++代码是:

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;
        }
};
Run Code Online (Sandbox Code Playgroud)

为了编写类似的Haskell代码,我创建了一个数据类型Rectangle

data Rectangle = Rectangle Length Width deriving (Eq, Show , Read)
type Length = Int
type Width = Int
Run Code Online (Sandbox Code Playgroud)

然后我想到了一个可以作为构造函数的加载函数.但我不明白如何使用不同数量的参数实现函数重载.请帮忙.谢谢.

ДМИ*_*КОВ 22

您可以使用记录语法来实现该行为.

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

rectangle = Rectangle { len = 0, width = 0 }
Run Code Online (Sandbox Code Playgroud)

rectangle :: Rectangle 将是你的构造函数.

现在您可以定义一些Rectangle值:

?> let a = rectangle {len = 1}

?> a
Rectangle {len = 1, width = 0}
Run Code Online (Sandbox Code Playgroud)


ehi*_*ird 20

虽然它可以在Haskell做这样的重载,它没有考虑习惯,并可能会导致混乱的错误以后.相反,您应该只定义构造数据的函数:

point :: Rectangle
point = Rectangle 0 0

line :: Length -> Rectangle
line l = Rectangle l 0

square :: Int -> Rectangle
square a = Rectangle a a
Run Code Online (Sandbox Code Playgroud)

这允许您给出描述每个重载语义的明确名称,而不是依赖于给出的参数的数量和类型来消除歧义.

但是,如果您确实要编写重载版本,可以使用类型类轻松地完成:

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
Run Code Online (Sandbox Code Playgroud)

您需要{-# LANGUAGE FlexibleInstances #-}在文件的顶部进行编译.这样的技巧被标准Text.Printf库使用,但我不认为它是Haskell中重载的一个特别好的例子; 重载值的类型几乎总是有一些结构,而这里的整个结构都是由实例决定的,这可能会妨碍类型推理; 不仅如此,而且没有任何合理的法律来管理实例(实际上,这种类型过于笼统而不允许任何实例).

但是如果你真的想要这样做,你可以,虽然这通常是一个坏主意,但有时(如在案例中printf)它是完成你想要的界面的唯一方法.

要在GHCi中尝试这一点,您需要明确指定您正在使用的类型,否则它将无法解析实例:

GHCi> rectangle :: Rectangle
Rectangle 0 0
GHCi> rectangle (1 :: Length) :: Rectangle
Rectangle 1 0
GHCi> rectangle (1 :: Length) (2 :: Width) :: Rectangle
Rectangle 1 2
Run Code Online (Sandbox Code Playgroud)