【发布时间】:2016-06-04 00:17:42
【问题描述】:
最近的一位最好匿名的发帖人试图像这样实现阶乘函数:
f :: Int -> Int
f = fix f
这显然效果不太好。但后来我想知道:我可以让它通过类型检查器吗?它的类型会揭示什么?
【问题讨论】:
-
哇...我没有得到
fact^^ 的部分 - 但感谢更新
标签: haskell recursion fixpoint-combinators
最近的一位最好匿名的发帖人试图像这样实现阶乘函数:
f :: Int -> Int
f = fix f
这显然效果不太好。但后来我想知道:我可以让它通过类型检查器吗?它的类型会揭示什么?
【问题讨论】:
fact ^^ 的部分 - 但感谢更新
标签: haskell recursion fixpoint-combinators
确实,由于多态递归,它会在给定更通用的类型时进行类型检查:
f :: a
f = fix f
通过参数化,我们立即可以看出它一定是底部,根据fix的定义,它一定是无限循环而不是异常。
chi comments,“出于同样的原因,f = bar f 将与任何 bar :: F a -> a “工作”,其中 F a 是任何类型(可能取决于 a)”。定义如下所示:
foo :: forall f a .
(forall b . f b -> b) -> a
foo g = g (foo g)
再一次,类型签名在参数上是伪造的,因为我可以选择,例如,f ~ Const Void,此时很明显,第一个参数对于产生结果是无用的。
【讨论】:
f = bar f 将与任何bar :: F a -> a“工作”,其中F a 是任何类型(可能取决于a)。例如。 proj2 :: (a,a) -> a。我实际上认为fix 并没有什么特别之处,它在这里被利用了。
fix,这些也类型检查:f3 :: a -> a ; f3 = fix f3 和f4 :: (a -> a) -> a -> a ; f4 = fix f4。仍然需要多态递归(当然!),但我发现有趣的是,我们的类型比 ::a 更多(我猜是无限多)。
seq 可以区分 ⊥、const ⊥、const (const ⊥) 等,所以最通用的 forall a . a 输入也是最多信息的。
forall a . a 类型的东西必须能够为任何a 生成a 类型的东西,而无需任何关于a 的信息。这是不可能的,但对于⊥。