Haskell 关于何时写作,何时使用的困惑$
给定上述函数,我不明白为什么Haskell 关于何时写作,何时使用的困惑$,haskell,Haskell,给定上述函数,我不明白为什么let x=sumOfSquares。returnGreatest2返回 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
let x=sumOfSquares。returnGreatest2
返回
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
:13:24:错误:
•无法将类型“a->a->(a,a)”与“c,c”匹配
预期类型:a->(c,c)
实际类型:a->a->a->(a,a)
•可能原因:“returnGreatest2”应用于太少的参数
在“(.”的第二个参数中,即“returnGreatest2”
在表达式中:sumOfSquares。返回最大值2
在“x”的方程式中:x=平方和。返回最大值2
•相关绑定包括
x::a->c(绑定时间:13:5)
但是
sumOfSquares$returngreatest23557
做了正确的事情。由于returnGreatest2
生成的类型与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)
相同;($)
运算符的优先级低于函数应用程序(或任何其他运算符)
要真正组合这两个函数,需要几个层次的组合:
<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)
()
函数的两边都应该是一个单参数函数,因此它将returnGreatest2
视为a->(a->a->(a,a))
。但是sumOfSquares
不接受(a->a->(a,a))
作为参数。一种方法是像以前一样使用$
,并应用所有参数,但也可以显式声明前两个参数:
let f = ((sumOfSquares .) . ) . returnGreatest2
这样,类型将匹配。您可以尝试此方法
let x a b = sumOfSquares . returnGreatest2 a b
x :: (Num c, Ord c) => c -> c -> c -> c
$
具有最低优先级returnGreatest2 3 5
是部分应用于3
和5
的函数returnGreatest2
,因此仍然是一个接受单个变量的函数。现在有两个函数接受一个变量:
sumOfSquares
returngreatest25
您可以使用
组合它们,这就是
的目的:使用单个变量输入和单个变量输出组合函数 我给你一个提示。合成运算符的类型是什么?请记住(::(b->c)->(a->b)->a->c的类型。但是returnGreatest2
需要4个参数,因此它应该应用3个参数(直到它的类型变成a->(a,a)
或者像上面的类型签名(a->b)
然后才能将其应用于复合运算符。例如让x=sumOfSquares.return2 3 5
,然后x7
将给出结果。下面是如何将多个参数的复合形式转换为无点形式的简短推导。\x y z->g((f x y)z)
=(合成的定义)=\x y->g.f x y
=(在前缀中重写)=\x y->(.g)(.f x)y
=(合成的定义)=\x->(.g.f x
=(在前缀中重写)=\x->(.g)(.g))(fx)
=(合成的定义)=(.g.).f
=(.code>实例函子(.a)
)=fmap(fmap g).f
。此处g
=sumOfSquares
和f
=returnGreatest2
。通常,要用n参数函数组成一个单参数函数,需要fmap
n− 1次。我更喜欢将无点版本写成fmap(fmap-sumOfSquares)。returnGreatest2
。fmap
与这里的()
相同(在(>)\uu
functor中),但imo更清楚:每个fmap
“映射”一个参数。为了清晰起见,包括额外的括号,fmap(fmap-sumOfSquares)
专门用于类型(a->a->(a,a))->(a->a->a)
,使其可与returnGreatest2::a->(a->a->(a,a))
组合。
sumOfSquares . returnGreatest2 3 5 $ 7