重载Haskell函数以具有不同数量的参数

时间:2017-05-17 22:48:09

标签: haskell

是否有可能在Haskell中有两个相同名称的函数具有不同数量的参数?这就是我想要做的事情:

inc = (+) 1

inc x = (+) x

我希望能够在没有参数的情况下调用我的增量函数,这些参数默认为递增1,或者使用参数并将其递增x。

我可以执行以下任一操作,例如:

map(inc)[1,2,3] - [2,3,4]

中的结果

map(inc 2)[1,2,3] - 结果为[3,4,5]

2 个答案:

答案 0 :(得分:8)

首先,简单的替代方法是为这种“默认参数”采用Maybe

inc :: Num a => Maybe a -> a -> a
inc Nothing x = 1 + x
inc (Just i) x = i + x

否则,是的,这是可能的,但它可能不值得。该技术是为具体类型(操作的结果)和函数(接受更多参数)创建一个类型类。(/ p>

我们介绍了可以作为增量结果的类型类:

class Inc i where
  inc :: Integer -> i

如果调用者需要一个整数,我们递增1:

instance Inc Integer where
  inc = (+) 1

如果调用者要求函数返回一个整数,我们按该函数的参数递增:

instance (Integral a) => Inc (a -> Integer) where
  inc x = (+) x . toInteger

现在这两个都有效:

map inc [1, 2, 3]
map (inc 2) [1, 2, 3] :: [Integer]

但是除非结果被使用结果的东西约束到[Integer],否则需要使用类型注释。如果您尝试使用诸如Num a => a之类的泛型类型而不是具体的Integer,或者如果您通过替换接受任何数量的参数,则类型推断会变得更糟(Integral a) => Inc (a -> Integer)的实例,(Integral a, Inc i) => Inc (a -> i)的实例。另一方面,您也可以为其他具体类型添加实例,例如IntDouble

我想我的反问题是:你实际上试图解决什么问题?

答案 1 :(得分:1)

不,这是不可能的。在Haskell中,函数的最新定义具有优先权。因此,如果您定义了两个版本的inc:

inc = (+) 1
inc x = (+) x

然后第二个定义 shadow 第一个定义。这意味着如果你打电话给" inc",现在将使用第二个定义。

但是,您仍然可以通过部分应用程序完成所需的操作。 如果你使你的2个电话咖喱,它将具有相同的效果。像这样:

map (inc 1) [1,2,3]

返回[2,3,4]

map (inc 2) [1,2,3]

返回[3,4,5]