我尝试进行以下功能定义:
relativelyPrime x y = gcd x y == 1
点免费:
relativelyPrime = (== 1) . gcd
然而,这给了我以下错误:
Couldn't match type ‘Bool’ with ‘a -> Bool’
Expected type: (a -> a) -> a -> Bool
Actual type: (a -> a) -> Bool
Relevant bindings include
relativelyPrime :: a -> a -> Bool (bound at 1.hs:20:1)
In the first argument of ‘(.)’, namely ‘(== 1)’
In the expression: (== 1) . gcd
In an equation for ‘relativelyPrime’:
relativelyPrime = (== 1) . gcd
我不太明白。 gcd
需要两个Ints / Integer,返回一个Ints / Integer,然后检查一个Int / Integer是否等于' 1'。我不知道我的错误在哪里。
答案 0 :(得分:7)
它不起作用,因为gcd
需要两个输入,而函数组合只提供gcd
一个输入。考虑函数组合的定义:
f . g = \x -> f (g x)
因此,表达式(== 1) . gcd
等同于:
\x -> (== 1) (gcd x)
这不是你想要的。你想要:
\x y -> (== 1) (gcd x y)
您可以定义一个新运算符来组成具有二元函数的一元函数:
f .: g = \x y -> f (g x y)
然后,你的表达式变为:
relativelyPrime = (== 1) .: gcd
事实上,(.:)
运算符可以根据函数组合来定义:
(.:) = (.) . (.)
它看起来有点像猫头鹰,但它们确实相当。因此,另一种写表达式的方法是:
relativelyPrime = ((== 1) .) . gcd
如果您想了解发生了什么,请参阅:What does (f .) . g mean in Haskell?
答案 1 :(得分:5)
正如您所评论的那样 - 如果您真的想要一个无点版本,您可以先使用uncurry gcd
将gcd
转换为接受单个输入(一个元组)的版本:
Prelude> :t uncurry gcd
uncurry gcd :: Integral c => (c, c) -> c
然后检查(== 1)
,最后再次curry
检查原始签名:
relativeelyPrime = curry ((== 1) . (uncurry gcd))
你的版本不起作用只是因为gcd
只产生一个函数,如果只给出了第一个参数,这对于等待数字的(== 1)
来说不是合法的输入。