Haskell中的Y组合子

Haskell中的Y组合子,haskell,y-combinator,Haskell,Y Combinator,可以用Haskell来写这个吗 它似乎具有无限递归类型 Y :: f -> b -> c where f :: (f -> b -> c) 或者别的什么。即使是一个简单的因子分解 factMaker _ 0 = 1 factMaker fn n = n * ((fn fn) (n -1) {- to be called as (factMaker factMaker) 5 -} “发生检查:无法构造无限类型:t=t->t2->t1”失败 (Y组合子看起来像这样

可以用Haskell来写这个吗

它似乎具有无限递归类型

 Y :: f -> b -> c
 where f :: (f -> b -> c)
或者别的什么。即使是一个简单的因子分解

factMaker _ 0 = 1
factMaker fn n = n * ((fn fn) (n -1)

{- to be called as
(factMaker factMaker) 5
-}
“发生检查:无法构造无限类型:t=t->t2->t1”失败

(Y组合子看起来像这样

(define Y
    (lambda (X)
      ((lambda (procedure)
         (X (lambda (arg) ((procedure procedure) arg))))
       (lambda (procedure)
         (X (lambda (arg) ((procedure procedure) arg)))))))
(计划中) 或者,更简洁地说

(λ (f) ((λ (x) (f (λ (a) ((x x) a))))
        (λ (x) (f (λ (a) ((x x) a))))))
适用顺序 及

对于懒惰的版本来说,这只是一个简单的过程

如果您喜欢短变量名。

及 似乎回答了我的问题。
稍后我会写更多的解释

现在,我发现了关于Mu类型的一些有趣的东西。考虑S=MuBOL。< /P>
data S = S (S -> Bool)
如果把S当作一个集合,把等号当作同构,那么方程就变成了

S ⇋ S -> Bool ⇋ Powerset(S)
所以S是一组与其功率集同构的集合! 但是我们从康托的对角论证中知道,幂集(s)的基数总是严格大于s的基数,所以它们从来都不是同构的。
我认为这就是为什么你现在可以定义一个固定点操作符,即使你不能没有它。

这里是haskell中y组合子的一个非递归定义:

newtype Mu a = Mu (Mu a -> a)
y f = (\h -> h $ Mu h) (\x -> f . (\(Mu g) -> g) x $ x)

Y组合子的标准定义如下:

y = \f -> (\x -> f (x x)) (\x -> f (x x))
但由于
x
,它不会在Haskell中键入check,因为它需要一个无限类型:

x :: a -> b -- x is a function
x :: a      -- x is applied to x
--------------------------------
a = a -> b  -- infinite type
如果类型系统允许这样的递归类型,那么类型检查将变得不可判定(容易出现无限循环)

但是,如果您强制Y组合器进行类型检查,例如通过使用:


这显然是不安全的。演示了一种在Haskell中编写不动点组合子而不使用递归的更安全的方法。

不能使用Hindley-Milner类型(Haskell类型系统所基于的多态lambda演算)对Y组合子进行类型化。您可以通过引用类型系统的规则来证明这一点

我不知道是否有可能通过给Y组合子一个更高秩的类型来输入它。这会让我惊讶,但我没有证据证明这是不可能的。(关键是为lambda绑定的
x
确定合适的多态类型)

如果希望在Haskell中使用定点运算符,可以非常轻松地定义一个,因为在Haskell中,let binding具有定点语义:

fix :: (a -> a) -> a
fix f = f (fix f)
您可以用通常的方法来定义函数,甚至是一些有限或无限的数据结构

也可以使用递归类型上的函数来实现不动点

如果您对使用定点编程感兴趣,可以阅读Bruce McAdam的技术报告。

只是为了使的代码更具可读性:

--Mu::(Mu a->a)->Mu a
新类型Mu a=Mu(Mu a->a)
w::(MUA->a)->a
w h=h(μh)
y::(a->a)->a
yf=w(\(μx)->f(wx))
--yf=f。y-f

其中,
w
代表ω组合器
w=\x->x
y
代表y组合器
y=\f->w。(f w)

正如另一个答案所示,如果你想要一个定点组合器,你可以只写
yf=f(yf)
而不给出类型,编译器将自己推断类型
(t->t)->t
。这是一个不同的定点组合,而不是严格意义上的y组合,正如维基百科文章所示。很好!这正是
unsafectoerce
的目的:绕过类型系统的限制。“虽然这是一个很好的类型,但它没有在Haskell中进行类型检查,因为
x
”该语句是矛盾的。事实上,类型理论的发明基本上是为了禁止自我应用。不可能用更高等级的类型来类型y组合子——系统F是强规范化的。另一方面,用递归类型来类型y组合子是很简单的
import Unsafe.Coerce

y :: (a -> a) -> a
y = \f -> (\x -> f (unsafeCoerce x x)) (\x -> f (unsafeCoerce x x))

main = putStrLn $ y ("circular reasoning works because " ++)
fix :: (a -> a) -> a
fix f = f (fix f)