1

我必须推导出这个函数的类型:

func x = map -1 x

而且我已经找到了一种方法,使用提示将其更改为 lambda 表达式:

func = \x -> (map) - (1 x)

如果我这样表达,它很好,我得到与原版相同的类型,但我不确定为什么它会这样分组。有人可以解释一下吗?

例如,为什么不是这样:

func = \x -> (map - 1) x

或类似的东西。

我知道这是一个无用的函数等,但我不能更改函数,我只需要导出它的类型。

如果你把这个函数写在一个文件中,例如:test.hs has func x = map -1 x and use :t funcin the interpreter,它会回复:

func :: (Num (t -> (a -> b) -> [a] -> [b]),
         Num ((a -> b) -> [a] -> [b])) =>
         t -> (a -> b) -> [a] -> [b]
4

3 回答 3

4

我现在相信你是想问为什么

func x = map -1 x

具有类型(Num (t -> (a -> b) -> [a] -> [b]), Num ((a -> b) -> [a] -> [b])) => t -> (a -> b) -> [a] -> [b],以及如何将表达式括起来以使其具有该类型。

首先,您必须认识到空格是haskell 中的运算符,并且具有最高的优先级。

让我们使用#而不是空格,我们可以使用最高优先级:

infixl 9 #
f # x = f x

我们可以在没有运算符的情况下用#替换和空格:

func x = map - 1 # x

因为 1 和 x 之间的空间是唯一没有运算符的空间(-is between mapand 1)。

由于#优先级高于-,我们得到

func x = map - (1 # x)

或等效地

func x = map - (1 x)

另一个例子

func2 x = map (-1) x
> :t func2
func2 :: Num (a -> b) => [a] -> [b]

这翻译为

func2' x = map # (-1) # x

-但是为什么在和之间没有# 1?在这种情况下,在类似mean-的数字文字前面:1negate

> (-1)
-1
> (negate 1)
-1
> (subtract 1)
<interactive>:73:1:
    No instance for (Show (a0 -> a0))
      arising from a use of `print'
    Possible fix: add an instance declaration for (Show (a0 -> a0))
    In a stmt of an interactive GHCi command: print it

所以这个函数试图将 1 的负数映射到一个列表上。为此,它需要负 1 才能成为一个函数,这就是为什么它需要一个函数的数字实例(Num (a->b) =>在类型的开头)。

于 2013-05-28T18:16:45.747 回答
2

但我不确定为什么它会这样分组。有人可以解释一下吗?例如,为什么不是这样:

   func = \x -> (map - 1) x

优先权。语言定义规定(前缀)函数应用的优先级高于任何中缀运算符,所以

map -1 x

被解析为中缀运算符(-)对两个操作数的应用,map1 x, like3 + 4 * 5被解析是3 + (4 * 5)因为 的优先级高于(*)(+)

于 2013-05-28T17:44:37.700 回答
1

虽然解释器已经为表达式分配了一个类型,但它不是一个明智的类型。让我们看看函数应该是什么

func x = map -1 x

看起来我们想像这样把它括起来

func x = map (-1) x

希望它从列表的每个元素中减去一个,但不幸的-是,当它在数字文字前面时,它被认为是否定,因此我们需要将它括起来以将其更改为减法函数:

func x = map ((-) 1) x

现在这个函数从 1 中减去列表中的每个数字:

 func [1,2,3]
=[(-) 1 1,  (-) 1 2,   (-) 1 3]
=[  1-1,      1-2,        1-3]
=[   0,       -1,         -2]

类型是

func :: Num a => [a] -> [a]

如果您想从列表的每个元素中减去一个,而不是从 1 中减去列表的每个元素,您可以使用func x = map (subtract 1) x. 正如 hammar 指出的那样,该subtract功能的存在正是为了实现这一点。


你的选择

func = \x -> (map - 1) x

这是行不通的,因为(-)has type Num a => a -> a -> a,而maphas type (a -> b) -> [a] -> [b]。您不能从函数中减去 1,因为函数不是数值。

于 2013-05-28T17:36:30.900 回答