控制功能

时间:2012-03-03 11:56:25

标签: function haskell syntax arity

我正在阅读这个问题的答案:Haskell: difference between . (dot) and $ (dollar sign)而且回复让我感到奇怪......他的意思是什么+没有输入?然后我尝试了:

((+) 1)
((+) 1 1)
((+) 1 1 1)
哎呀......伤心的消息。但我确信我看到的功能可能看似任意或大量的论据,认为某人已经以a-> b-> c ...-> z的方式定义了它们。必须有一些方法来处理它!我正在寻找的是像CL中的& rest或& optional。

2 个答案:

答案 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参数版本的结果。

因此,语言设计师需要做出选择。

  • Haskell选择了很好的函数应用程序语法(不需要括号)
  • Lisp选择变量arity函数(并添加括号以消除歧义)