Haskell “的行为;常数id“;

Haskell “的行为;常数id“;,haskell,Haskell,我正在研究99个Haskell问题,并找到了查找列表最后一个元素的解决方案: myLast = foldr1 (const id) const的类型是a->b->a,而const-id的类型是b->a->a 那么这里的魔力是什么呢?id的类型是c->c;它只返回与给定的内容相同的内容 const的类型是a->b->a。在const id中,a变为c->c,因此在这种情况下,const的类型变为: (c->c) -> b -> (c->c) 既然您已经应用了这个常量

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

  myLast = foldr1 (const id)
const
的类型是
a->b->a
,而
const-id
的类型是
b->a->a


那么这里的魔力是什么呢?

id的类型是
c->c
;它只返回与给定的内容相同的内容

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

(c->c) -> b -> (c->c)
既然您已经应用了这个常量函数,也就是说,您已经向它传递了
id
,那么剩下的就是
b->(c->c)


注:
const-const-id
的类型是
a->b->a
const-const-id
的类型是
b->a->a
,依此类推

没有魔法。
const
的定义是:

const :: a -> b -> a
const x y = x
id :: a -> a
id x = x
id
的定义是:

const :: a -> b -> a
const x y = x
id :: a -> a
id x = x
所以
const id
就是
\y->id
,一个总是返回
id
的函数。如果
id
只是
\x->x
,那么
常量id
必须与
\y->\x->x
相同。因此,它有类型
b->(a->a)


const-id
也可以写入
flip-const
。既然
const
\x->\y->x
,那么
flip const
以相反的顺序接受参数,
\y->\x->x
,这与
const id
的工作原理相同

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

需要记住的一个重要概念是局部应用

我理解这一点的方式是,在Haskell中,我们可以将函数的一个参数“修复”为已知值,因此现在函数接受的参数少了一个

概述:const的类型为:

const :: a -> b -> a
作为一个简单的例子,让我们“修复”第一个参数为(+)

现在我们已经修复了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”

嗯,是的,除了在哈斯克尔中那些括号可以省略。

这也是有意义的,因为您可以立即为“id”函数提供它所需的额外参数(如上面的“const(+)”示例)。

我最终理解这一点的唯一方法是想象Haskell在计算类似
const id 1 2
的表达式时所采取的步骤序列。首先考虑这些陈述:

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

不过,函数应用程序与左边的关联:fxy实际上是(fx)y

记住这一点,从上面看,
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的新手。

难怪,因为
const foo bar=foo
。还请注意,
const-id
flip-const
,或
flip-const-flip-const-flip-const-flip-const-id-const-id
;)相同当然,
ap
const
是计算任何内容所需的两个函数。(这是读者monad提供的
ap
)@luqui-True,有了类型检查器,你需要一些新的类型包装器或类似的东西。也许你应该提出一个新问题,列出在真实案例中使用的这些小而有趣但功能强大的函数b->(c->c)在这种情况下意味着:id b(我想分享,但我花了一段时间才弄明白。)为了补充提供的答案,回想一下Haskell中的所有函数都是curry,因此
a->(b->c)
a->b->c
相同,但它有一个更具情境性的答案,这可能更清楚,具体取决于您的思维过程。