可以修复只能输入非严格评估的语言吗?

时间:2018-01-25 16:04:13

标签: haskell recursion typechecking fixed-point unification

我在Javascript中编写了一个运行时类型检查器,并且无法键入fix

fix :: (a -> a) -> a
fix f = ...

fix (\rec n -> if n == 0 then 1 else n * rec (n-1)) 5 -- 120

传递给fix的阶乘函数具有简化类型(Int -> Int) -> Int -> Int

当我尝试在Javascript中重现表达式时,由于无效约束Int ~ Int -> Int,我的类型检查程序失败。

fix (const "hallo")也失败了,类型检查员抱怨它无法构造无限类型(负面发生检查)。

使用其他组合器,我的统一结果与Haskell的结果一致。

我的统一算法可能是错误的还是fix只能在非严格的环境中输入?

[编辑]

我在Javascript中fix的实施是const fix = f => f(f)

2 个答案:

答案 0 :(得分:4)

It's a bug in the type checker.

It is true though that the naive Haskell definition of fix does not terminate in Javascript:

> fix = (f) => f(fix(f))
> factf = (f) => (n) => (n === 0) ? 1 : n * f(n - 1)
> fact = fix(factf) // stack overflow

You'd have to use an eta-expanded definition in order to the prevent looping evaluation of fix(f):

> fix = (f) => (a) => f(fix(f), a)
> factf = (f, a) => (a == 0) ? 1 : a * f(a - 1)
> fact = fix(factf)
> fact(10) // prints 3628800

答案 1 :(得分:0)

事实证明,你试图实现 U 组合子,它是不是定点组合子。

而定点 Y 组合子_Y g = g (_Y g)使我们能够写

    _Y (\r x -> if x==0 then 1 else x * r (x-1)) 5     -- _Y g => r = _Y g
    -- 120

_U g = g (g)我们必须写

    _U (\f x -> if x==0 then 1 else x * f f (x-1)) 5    -- _U g => f = g, f f == _U g

正如您所发现的, _U 在Haskell中没有类型。一方面g是一个函数g :: a -> b;另一方面,它接收自己作为第一个参数,因此它要求{em>任何类型a ~ a -> ba b

a -> b替换为a 中的a -> b 会导致无限递归(参见"发生检查"),因为{ {1}}仍有(a -> b) -> b需要替换为a;无限的。

解决方案可能是引入递归类型,将a -> b转换为a ~ a -> b,即

R = R -> b

所以我们可以定义

    newtype U b = U {app :: U b -> b}                      -- app :: U b -> U b -> b

现在有一个类型;并将其用作

    _U :: (U b -> b) -> b
    _U g = g (U g)                                         -- g :: U b -> b 

编辑:如果您想将 Y 组合子实现为非递归定义,那么

    _U (\f x -> if x==0 then 1 else x * app f f (x-1)) 5   -- _U g => f = U g, app f f = 
    -- 120                                           -- app (U g) (U g) = g (U g) == _U g

所以

    _U (\f x -> if x==0 then 1 else x * (app f f) (x-1))               -- abstraction:
   =                                    -------.-
    _U (\f -> (\r x -> if x==0 then 1 else x * r (x-1)) (app f f))     -- abstraction:
   =          -------.---------------------------------
    (\g -> _U (\f -> g (app f f))) (\r x -> if x==0 then 1 else x * r (x-1))
   =                                                                   --    r = app f f 
    _Y                             (\r x -> if x==0 then 1 else x * r (x-1))

完成工作:

    _Yn :: (b -> b) -> b
    _Yn g = _U (\f -> g (app f f))                                -- Y, non-recursively