“const id”的行为

时间:2012-01-05 15:28:36

标签: haskell

我正在研究99个Haskell问题,并找到了一个找到列表最后一个元素的解决方案:

  myLast = foldr1 (const id)

const的类型为a -> b -> aconst id的类型为b -> a -> a 那么这里的魔力是什么?

4 个答案:

答案 0 :(得分:42)

id的类型为c->c;它只会返回相同的东西。

const的类型为a->b->a。在const id中,a变为c->c,因此在这种情况下const的类型变为:

(c->c) -> b -> (c->c)

既然你已经应用了这个const函数,即你已经将id传递给它,那么你将留下b -> (c->c)

PS const const id的类型为a->b->aconst const const id的类型为b->a->a,依此类推!

答案 1 :(得分:23)

没有魔力。 const的定义是:

const :: a -> b -> a
const x y = x

id的定义是:

id :: a -> a
id x = x

所以const id只是\y -> id,这个函数总是返回id。如果id只是\x -> x,则const id必须与\y -> \x -> x相同。因此,它的类型为b -> (a -> a)

const id也可以写成flip const。由于const\x -> \y -> x,因此flip const采用相反顺序的参数\y -> \x -> x,与const id相同。

答案 2 :(得分:7)

以下是我对其运作方式的理解。

这是我能想到的最简单的解释,我试图(故意)避免任何可能混淆的概念或单词。

要记住的一个重要概念是部分应用。

我理解这一点的方法是,在Haskell中我们可以将函数的一个参数“修复”到一个已知值,所以现在该函数只接受一个参数。

回顾:const的类型是:

const :: a -> b -> a

作为一个更简单的例子,让我们将第一个参数“修复”为(+)

let f = const (+)

现在我们已经修复了const的第一个参数,“f”是一个只接受单个参数的函数。 但是因为const总是返回它的第一个参数,我们已经修复了它,这意味着我们传递给“f”的任何东西都将被忽略,它将始终返回函数“+”。

作为示例,以下所有内容都将给出5,因为f将始终返回函数“+”,而不管它作为第一个参数接收到什么,而函数“+”将在2和3上运行:

f “aaa”        2 3
f  904212      2 3
f  undefined   2 3

f的类型是:

f :: b -> Integer -> Integer -> Integer

请注意,“b”可以是任何内容,如上所示。

现在有问题的实际功能:

g = const id

这意味着我们将id“固定”为第一个参数,如上所述,“g”忽略其第一个参数并返回函数“id”。 在Haskell中,我们可以继续前进并为“id”提供额外的参数,就像我们对上面的(+)所做的那样,例如所有这些都将返回42:

g  “aaa”     42
g  undefined 42

所以“g”是接受两个参数的函数,并且总是返回第二个参数,所以它的类型是:

g = const id :: b -> a -> a

但是等一下,我在那里做了一个巨大的飞跃。不应该是这样的类型:

b -> (a -> a) 

因为我们只是说我们接受任何东西并返回“id”?

嗯,是的,除了在Haskell中,这些括号可以省略 它也有意义,因为你可以立即提供所需额外参数的“id”函数(如上面的“const(+)”示例)。

答案 3 :(得分:1)

我最终掌握这一点的唯一方法是想象Haskell在评估像const id 1 2这样的表达式时所采取的步骤顺序。首先考虑这些陈述:

  

在Haskell中,所有函数都被认为是curry:也就是说,Haskell中的所有函数只接受一个参数。 1

     

功能应用虽然与左边相关:f x y实际上是(f x)y。 1

考虑到这一点,从上面看const需要两个参数而id需要一个参数,我们可以看到以下步骤:

const id 1 2   -- Haskell evaluates 'const id' and returns a function (we can call it
               -- 'constId') which accepts one argument and always returns 'id'

constId 1 2    -- Haskell now evaluates 'constId 1', which as expected just returns 'id'

id 2           -- 'id' is now applied to 2, which just returns '2'

2              -- final result

免责声明:我是Haskell的新手。