我必须派生出这个函数的类型:
func x = map -1 x
我已经找到了一种方法,使用提示将其更改为lambda表达式:
func = \x -> (map) - (1 x)
如果我这样表达,它的罚款和我的原型相同,但我不确定为什么它这样分组。有人可以解释一下吗?
例如,为什么不是这样的:
func = \x -> (map - 1) x
或类似的东西。
我知道这是一个无用的功能等但我无法改变功能,我只需要派生它的类型。
如果您在文件中编写此函数,例如:
test.hs有func x = map -1 x
并在解释器中使用:t func
,它将回复:
func :: (Num (t -> (a -> b) -> [a] -> [b]),
Num ((a -> b) -> [a] -> [b])) =>
t -> (a -> b) -> [a] -> [b]
答案 0 :(得分: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之间的空格是唯一没有运算符的空格(-
介于map
和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
之间没有#?在这种情况下,-
等数字文字前面的1
表示negate
:
> (-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) =>
)。
答案 1 :(得分:2)
但我不确定为什么它这样分组。有人可以解释一下吗?例如,为什么它不是那样的:
func = \x -> (map - 1) x
map -1 x
被解析为中缀运算符(-)
应用于两个操作数map
和1 x
,因为3 + 4 * 5
被解析3 + (4 * 5)
因为更高(*)
的优先级与(+)
的优先级相比。
答案 2 :(得分: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
这不起作用,因为(-)
的类型为Num a => a -> a -> a
,而map
的类型为(a -> b) -> [a] -> [b]
。您不能从函数中减去一个函数,因为函数不是数值。