对于此功能:
foo :: (b -> c) -> (a -> b) -> (a -> c)
取自http://www.seas.upenn.edu/~cis194/spring13/lectures/04-higher-order.html
这是一个没有实际用途的功能吗?由于类型c是此函数中的另一个输入参数,因此无法构造(b -> c)
同样适用于(a -> b) -> (a -> c)
:b& c不是这些函数的输入参数。
此功能是否有用例?
答案 0 :(得分:5)
如果问题是关于在实践中使用函数组合,这里有一个小例子。让我们假设我们想要编写一个函数,该函数是数字列表中所有元素的平方和。我们怎么能这样做?好吧,我们可以这样写:squareSum xs = sum (map (^2)) xs
。但我们也可以使用函数组合:squareSum = sum . map (^2)
(我在这里使用.
代替foo
而不是{{1}},但这并不重要。此示例显示了使用函数组合获得的函数(至少在编译和正常工作的意义上它是实用的)。当我们需要组合多个函数(可能部分应用)时,函数组合的好处变得更加明显。
答案 1 :(得分:2)
可以构造函数b -> c
- 因为b
和c
可以是任何类型,然后任何函数都与它兼容。但是,函数foo
不能本身(明智地)构造这样的函数,因为它不知道b
和c
。这是一个很大的好处,因为它大大减少了函数foo
的可能实现的数量。这称为parametricity
此函数是函数组合运算符(.)
的类型:
答案 2 :(得分:0)
我只想说明System.out.println("Minutes " + (diffInHours - (int)diffInHours)*60 );
可能位于任何优秀Haskell代码库中前三个最常用函数中的某个位置。它肯定在我的代码中。
前三者中的另外两个是由于积分文字而由编译器插入的(.)
的隐式调用,以及来自fromInteger
符号的(>>=)
的隐式调用。从深层意义上讲,后者与do
具有相同的操作,但对于形状略有不同的类型的操作。
答案 3 :(得分:0)
为了补充其他答案,让我试着证明只有一个(总)函数
foo :: (b -> c) -> (a -> b) -> (a -> c)
或换句话说,foo = (.)
。通过扩展性,我们想要证明
foo f g n = f (g n)
其中f,g,n
是由foo
签名规定的类型的非法值。
f :: b -> c
g :: a -> b
n :: a
我们从相关的自由定理开始,可以是automatically generated on the web:
forall t1,t2 in TYPES, R in REL(t1,t2).
forall t3,t4 in TYPES, S in REL(t3,t4).
forall t5,t6 in TYPES, R1 in REL(t5,t6).
forall p :: t3 -> t5.
forall q :: t4 -> t6.
(forall (x, y) in S. (p x, q y) in R1)
==> (forall r :: t1 -> t3.
forall s :: t2 -> t4.
(forall (z, v) in R. (r z, s v) in S)
==> (forall (w, u) in R.
(foo p r w, foo q s u) in R1))
让我们通过专业化来简化这个庞大的公式。我们选择:
t1 = a t2 = ()
t3 = b t4 = ()
t5 = c t6 = ()
我们选择如下关系:
R = { (n , ()) } which is indeed in REL(t1,t2) = REL(a,())
S = { (g n , ()) } which is indeed in REL(t3,t4) = REL(b,())
R1= { (f (g n) , ()) } which is indeed in REL(t5,t6) = REL(c,())
自由定理变为:
forall p :: b -> c.
forall q :: () -> ().
(forall (x, y) in S. (p x, q y) in R1)
==> (forall r :: a -> b.
forall s :: () -> ().
(forall (z, v) in R. (r z, s v) in S)
==> (forall (w, u) in R.
(foo p r w, foo q s u) in R1))
根据p = f
和q = id
的定义,我们获取S
和R1
(forall x = g n, y = () . f x = f (g n) /\ y = id y)
==> (forall r :: a -> b.
forall s :: () -> ().
(forall (z, v) in R. (r z, s v) in S)
==> (forall (w, u) in R.
(foo f r w, foo id s u) in R1))
顶级含义的前提是正确的,所以我们解除它。
我们现在选择r = g
和s = id
。根据{{1}}和r1
:
R
我们可以解除真正的前提。此外,我们可以选择 (forall z = n, v = () . g z = g n , id v = ())
==> (forall (w, u) in R.
(foo f g w, foo id id u) in R1)
和w = n
。我们终于获得了:
u = ()
<强> Q.E.D。强>