“const id”的行为
我正在处理99个Haskell问题,并且看到了一个用于查找列表的最后一个元素的解决scheme:
myLast = foldr1 (const id)
const
的types是a -> b -> a
但const id
是b -> a -> a
那么这里有什么魔力?
id
的types是c->c
; 它只是返回它给出的相同的东西。
const
的types是a->b->a
。 在const id
, a
变成c->c
,所以在这种情况下const的types变成:
(c->c) -> b -> (c->c)
现在你已经应用了这个const函数,也就是你已经传递了id
,那么你就剩下了b -> (c->c)
。
PS : const const id
的types是a->b->a
, const const const id
的types是b->a->a
,依此类推!
没有魔法。 const
的定义是:
const :: a -> b -> a const xy = x
id
的定义是:
id :: a -> a id x = x
所以const id
就是\y -> id
,一个总是返回id
的函数。 如果id
只是\x -> x
那么const id
必须与\y -> \x -> x
。 Ergo,它有typesb -> (a -> a)
。
const id
也可以写成flip const
。 由于const
是\x -> \y -> x
,所以flip const
以相反的顺序取参数\y -> \x -> x
,这与const id
相同。
这是我对这是如何工作的理解。
这是我能想到的最简单的解释,我尝试(有意)以避免任何可能混淆的概念或单词。
要记住的一个重要概念是部分应用。
我理解的方式是,在Haskell中,我们可以将函数的某个参数“固定”为一个已知的值,所以现在函数只接受一个参数。
回顾一下:const的types是:
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的types是:
f :: b -> Integer -> Integer -> Integer
请注意,“b”可以是任何东西,如上所述。
现在讨论实际的function:
g = const id
这意味着我们将“固定”id作为第一个参数,因此如上所述,“g”忽略其第一个参数并返回函数“id”。 在Haskell中,我们可以继续前进,并为“id”提供额外的参数,就像我们对(+)所做的那样,例如所有这些都会返回42:
g “aaa” 42 g undefined 42
所以“g”是接受两个参数的函数,总是返回第二个参数,所以它的types是:
g = const id :: b -> a -> a
但是等一下,我刚刚在那里做了一个巨大的飞跃。 不应该是:
b -> (a -> a)
既然我们只是说,我们接受任何东西,并返回“ID”?
那么,是的,除了在Haskell中,这些括号可以省略。
这也是有道理的,因为你可以立即提供所需的额外参数(如上面的“const(+)”示例)的“id”函数。
我终于明白了这一点的唯一方法是想象Haskell在评估一个像const id 1 2
这样的expression式时所采用的步骤顺序。 首先考虑这些陈述:
在Haskell中,所有函数都被认为是curried:也就是说,Haskell中的所有函数都只有一个参数。 1
function应用虽然,联系在左边:fxy是真的(fx)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的新手。