是否有可能在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]
答案 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)
的实例。另一方面,您也可以为其他具体类型添加实例,例如Int
和Double
。
我想我的反问题是:你实际上试图解决什么问题?
答案 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]