我正在阅读这个问题的答案:Haskell: difference between . (dot) and $ (dollar sign)而且回复让我感到奇怪......他的意思是什么+
没有输入?然后我尝试了:
((+) 1)
((+) 1 1)
((+) 1 1 1)
哎呀......伤心的消息。但我确信我看到的功能可能看似任意或大量的论据,认为某人已经以a-> b-> c ...-> z的方式定义了它们。必须有一些方法来处理它!我正在寻找的是像CL中的& rest或& optional。
答案 0 :(得分:11)
当然,你可以定义一个可变加法函数,有一些类型类hackery: 1
{-# LANGUAGE TypeFamilies #-}
class Add r where
add' :: (Integer -> Integer) -> r
instance Add Integer where
add' k = k 0
instance (n ~ Integer, Add r) => Add (n -> r) where
add' k m = add' (\n -> k (m+n))
add :: (Add r) => r
add = add' id
所以:
GHCi> add 1 2 :: Integer
3
GHCi> add 1 2 3 :: Integer
6
标准Text.Printf
模块使用相同的技巧。它通常被避免有两个原因:第一,它给你的类型可能很难处理,你经常需要指定一个明确的类型签名供你使用;二,它真的是一个黑客,应该很少使用,如果有的话。 printf
必须使用任意数量的参数和是多态的,因此它不能简单地列出一个列表,但是为了补充,您可以使用sum
。
1 语言扩展在这里并不是必需的,但是它们使用起来更容易(没有它们,你必须在示例中明确指定每个参数的类型)我给了,例如add (1 :: Integer) (2 :: Integer) :: Integer
)。
答案 1 :(得分:2)
这是一种语法上的权衡:你不能(通常)同时具有变量arity函数和用于函数应用的漂亮的Haskell样式语法。这是因为它会使许多表达模糊不清。
假设你有一个允许1或2的arity的函数foo,并考虑以下表达式:
foo a b
这里应该使用foo的1或2参数版本吗?编译器无法知道,因为它可能是2参数版本,但它同样可能是应用于b的1参数版本的结果。
因此,语言设计师需要做出选择。