Haskell不动点签名

Haskell不动点签名,haskell,functional-programming,Haskell,Functional Programming,以下Haskell函数的签名是什么: fix f = f (fix f) a) ((a->b)->a->b)->a->b b) 签名无法合成 c) (a->a)->a 谢谢 这个问题看起来像是一个课程作业/测试问题。我将帮助您自己找到解决方案: 首先,您可能安装了GHC,因此可以运行haskell repl 有。但它相当长 如果启动GHCi,将出现一个提示,您可以在其中键入Haskell表达式: Prelude> 1 + 1 2 Prelude> map (\x -> x +

以下Haskell函数的签名是什么:

fix f = f (fix f)
a) ((a->b)->a->b)->a->b

b) 签名无法合成

c) (a->a)->a


谢谢

这个问题看起来像是一个课程作业/测试问题。我将帮助您自己找到解决方案:

首先,您可能安装了GHC,因此可以运行haskell repl

有。但它相当长

如果启动GHCi,将出现一个提示,您可以在其中键入Haskell表达式:

Prelude> 1 + 1
2
Prelude> map (\x -> x + x) [1, 2, 3]
[2,4,6]
还可以将表达式绑定到名称,并定义函数:

Prelude> let fix f = f (fix f)
最强大的功能之一是询问表达式的类型:

Prelude> :t map (\x -> x + x)
map (\x -> x + x) :: Num b => [b] -> [b]
Prelude> :t fix
... output omitted

这就是你如何找到解决问题的方法。知道这一点后,您可以问为什么修复的类型是这样的。

一种完全不同的方法:通过推理找到解决方案

右手边是

f (fix f)
因此,对于某些类型的
a
b
,f具有类型
a->b
,因为
f
是一个函数

换句话说,
f(fixf)
的值具有类型
b
,而
fixf
具有类型
a

因为根据定义

fix f = f (fix f)
fix f
必须具有与
f(fix f)
相同的类型,即
b

我们已经说过
a
fixf
的类型,因此
a
b
必须是同一类型

让我们称之为
t
来保持事物的独立性

因此
f:t->t
,因为
a
b
是同一类型
t

我们知道
fixf
的类型为
b
,我们将其重命名为
t

f:t->t
fix f:t
放在一起,我们得到了

fix : (t -> t) -> t  
这是备选方案c)


旁白:如果我们用
a->b
代替
t
我们得到

((a -> b) -> (a -> b)) -> (a -> b)
或者,由于箭头与右侧关联:

((a -> b) -> a -> b) -> a -> b
这正是a中的答案。

因此a)几乎是正确的,但不够笼统。

你可以试着把它放在REPL中,自己看看。更具体地说,在GHCi中定义
fix
,使用
let fix f=f(fix f)
,然后用
:t fix
询问它的类型。我投票结束这个问题,因为我也不想做你的家庭作业。可能重复为什么你不停在
fix:(t->t)->t
。这是正确且主要的HM类型,它等于(模重命名)c)。若问题是多项选择题,我认为a)和c)都是正确的。或者任何一个都可以(任何正确的类型)。@phadej我确实在这里停了下来,但我编辑了一下,希望能让它更清楚一点。最后的旁白是为了解释备选方案a)不够笼统。