我在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)
。
答案 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 -> b
和a
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