returnGreater :: (Ord a) => a -> a -> a
returnGreater a b
| (a > b) = a
| otherwise = b
returnGreatest2 :: (Ord a, Num a) => a -> a -> a -> (a, a)
returnGreatest2 a b c
| (a > b) = (a, returnGreater b c)
| otherwise = (b, returnGreater a c)
sumOfSquares :: (Num a) => (a, a) -> a
sumOfSquares (a, b) = a^2 + b^2
鉴于上述功能,我很困惑为什么let x = sumOfSquares . returnGreatest2
返回
<interactive>:13:24: error:
• Couldn't match type ‘a -> a -> (a, a)’ with ‘(c, c)’
Expected type: a -> (c, c)
Actual type: a -> a -> a -> (a, a)
• Probable cause: ‘returnGreatest2’ is applied to too few arguments
In the second argument of ‘(.)’, namely ‘returnGreatest2’
In the expression: sumOfSquares . returnGreatest2
In an equation for ‘x’: x = sumOfSquares . returnGreatest2
• Relevant bindings include
x :: a -> c (bound at <interactive>:13:5)
但是sumOfSquares $ returnGreatest2 3 5 7
做正确的事。由于returnGreatest2
产生的类型与sumOfSquares
期望的类型相同,所以我认为我可以组成它们。
答案 0 :(得分:5)
组成和咖喱可能会有些混乱。 sumOfSquares . returnGreatest2
与\x -> sumOfSquares (returnGreatest2 x)
相同,但是returnGreatest2 x
的类型为(Ord a, Num a) => a -> a -> (a, a)
。在最终获得(Ord a, Num a) => (a, a)
可以接受的sumOfSquares
类型的值之前,您需要传递所有期望的参数。
另一方面,sumOfSquares $ returnGreatest2 3 5 7
的解析与sumOfSquares $ (returnGreatest2 3 5 7)
相同; ($)
运算符的优先级比函数应用程序(或其他任何运算符)低。
要真正组合这两个功能,您需要多层组合:
let f = ((sumOfSquares .) . ) . returnGreatest2
答案 1 :(得分:4)
(.)
函数的两侧都应为单个参数函数,因此它将returnGreatest2
视为a -> (a -> a -> (a, a))
。但是sumOfSquares
不接受(a -> a -> (a, a))
作为参数。一种实现方法是像以前一样使用$
并应用所有参数,但是您也可以明确声明前两个参数:
let x a b = sumOfSquares . returnGreatest2 a b
x :: (Num c, Ord c) => c -> c -> c -> c
这样类型将匹配。
答案 2 :(得分:2)
您可以尝试
sumOfSquares . returnGreatest2 3 5 $ 7
$
的优先级最低。 returnGreatest2 3 5
是函数returnGreatest2
的一部分,部分应用于3
和5
,因此仍然是一个接受单个变量的函数。因此,现在您有两个接受单个变量的函数:
sumOfSquares
returnGreatest2 3 5
您可以用.
来构成它们,.
的目的是:组合一个带有单个变量输入和一个单个变量输出的函数。