这个函数有没有用例:foo ::(b - > c) - > (a - > b) - > (a - > c)

时间:2015-05-15 10:15:08

标签: haskell

对于此功能:

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不是这些函数的输入参数。

此功能是否有用例?

4 个答案:

答案 0 :(得分:5)

如果问题是关于在实践中使用函数组合,这里有一个小例子。让我们假设我们想要编写一个函数,该函数是数字列表中所有元素的平方和。我们怎么能这样做?好吧,我们可以这样写:squareSum xs = sum (map (^2)) xs。但我们也可以使用函数组合:squareSum = sum . map (^2)(我在这里使用.代替foo而不是{{1}},但这并不重要。此示例显示了使用函数组合获得的函数(至少在编译和正常工作的意义上它是实用的)。当我们需要组合多个函数(可能部分应用)时,函数组合的好处变得更加明显。

答案 1 :(得分:2)

可以构造函数b -> c - 因为bc可以是任何类型,然后任何函数都与它兼容。但是,函数foo不能本身(明智地)构造这样的函数,因为它不知道bc。这是一个很大的好处,因为它大大减少了函数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 = fq = id的定义,我们获取SR1

     (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 = gs = 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。