2017-05-17 68 views
1

Haskell中可能有两个具有相同名称的函数具有不同数量的参数吗?这就是我想做的事:重载Haskell函数以具有不同数量的参数

inc = (+) 1

inc x = (+) x

我希望能够到默认调用我的增值功能不带参数的递增1,或者用一个参数,并把它递增由x。

的我可以做以下任一,例如:

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

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

+1

你可以通过类型类有多个参数的功能,有点欺骗,例如见Development.Shake.cmd。虽然我想添加一个免责声明 - 这不是初学者的东西,更多的是一个中间话题 – epsilonhalbe

+6

作为另一个免责声明 - 即使在技术上可行的情况下,Haskell开发者也不是这样做的,因为它干扰了部分应用程序,我们一直使用*。这也是一种痛苦。 – luqui

+0

另请参阅:[增量式特设参数抽象](https://byorgey.wordpress.com/2010/04/03/haskell-anti-pattern-incremental-ad-hoc-parameter-abstraction/)。 –

回答

6

首先,简单的办法是只取了这个Maybe “默认参数”:

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

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

介绍之类的类型,可以作为一个增量的结果:

class Inc i where 
    inc :: Integer -> i 

如果呼叫者需要一个整数,我们增加一个:

instance Inc Integer where 
    inc = (+) 1 

如果来电者的需求一个返回整数的函数,我们通过该函数的参数递增:

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

N这些流量都工作:

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

但需要类型标注除非结果由使用结果的东西限制为[Integer]。如果您尝试使用泛型类型,如Num a => a,而不是具体的Integer,或者如果你把它用一个(Integral a, Inc i) => Inc (a -> i)更换实例(Integral a) => Inc (a -> Integer)接受任何数量的参数类型推断变得更糟糕。另一方面,您也可以为其他具体类型添加实例,例如IntDouble

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

1

不,这是不可能的。在Haskell中,函数的最新定义具有优先权。所以,如果你定义INC的两个版本:

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

然后第二个定义将阴影的第一个定义。这意味着如果你调用“inc”,现在将使用第二个定义。

然而,你仍然可以完成你想要的部分应用程序。 如果你让你的2个电话curried它会有同样的效果。像这样:

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

返回[2,3,4]

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

返回[3,4,5]